2018-03-10 刷题

1087 All roads 最短路径算法,所有的最短路径,各种回溯

这是我最近写过的最丑的代码,没有之一。太繁琐,变量名都起不过来,只能加注释,顾不上那么多了。发现所有 test case 都过了的时候我简直惊呆了。

在dijkstra最短路算法的基础上,对于路径一样长的情况都要存下来。

然后就可以递归回溯各种可能的路径,寻找happiness最大的或者平均happiness最大的。这里

# include <cstdio>
# include <cstring>

int N, K; //number of cities, number of roads
int dest;
int happy[200];
int cost[200][200];
char name[200][4];

int p[200][200]; //id of the city's parent
int np[200]; //number of parents
int dist[200]; // total cost of coming 
bool status[200]; //if its shortest dist is known

int nRoute = 0; //有多少条路线是最短路
int h, mh; //当前路线的happy, 最优路线的happy
int nNode, mnNode; //当前经历的节点,最优路线的节点数
int route[200], mRoute[200]; //当前路线,最优路线

int id(char *str) {
    for (int i = 0; i < N; i++) {
        if (strcmp(str, name[i]) == 0) {
            return i;
        }
    }
    return -1;
}

void read() {
    scanf("%d %d %s", &N, &K, name[0]); //start point at 0
    for (int i = 1; i < N; i++) {
        scanf("%s %d", name[i], happy + i);
    }
    dest = id("ROM");

    //init the graph
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            cost[i][j] = 1 << 30;
        }
        cost[i][i] = 0;
        dist[i] = (1 << 30);
    }

    for (int i = 0; i < K; i++) {
        char a1[4], a2[4];
        int d, ia1, ia2;
        scanf("%s %s %d", a1, a2, &d);
        ia1 = id(a1); ia2 = id(a2);
        cost[ia1][ia2] = (cost[ia2][ia1] = d);
    }
}

void dijk() {
    dist[0] = 0;
    while (1) {
        int m = 0, md = 1 << 30; //m = 最短路径未知的集合里距离最小的点
        for (int i = 0; i < N; i++) {
            if (!status[i] && dist[i] < md) {
                md = dist[i];
                m = i;
            }
        }
        if (m == 0 && status[0]) { //说明所有的点 status 都为真了,所以m才没变
            break;
        }

        status[m] = true; // 最短路已知
        for (int i = 0; i < N; i++) {
            if (!status[i] && cost[m][i] < (1 << 30)) { //有路
                if (cost[m][i] + dist[m] < dist[i]) { //比之前的路更短
                    np[i] = 1;
                    p[i][0] = m;
                    dist[i] = cost[m][i] + dist[m];
                }
                else if (cost[m][i] + dist[m] == dist[i]) { //和之前的路一样短
                    p[i][(np[i] ++)] = m;
                }
            }
        }
    }
}

void backward(int x) {
    route[nNode++] = x;
    h += happy[x];
    if (x == 0) { //回溯到了起点
        nRoute++;
        if (h > mh || (h == mh && (h / (float)nNode) > (mh / (float)mnNode))) { //更好的路线
            mh = h;
            mnNode = nNode;
            memcpy(mRoute, route, sizeof(int) * 200);
        }
    }
    else {
        for (int i = 0; i < np[x]; i++) { //i的每一个祖先
            backward(p[x][i]);
        }
    }
    h -= happy[x];
    nNode--;
}

int main() {
    read();
    dijk();

    backward(dest); 

    printf("%d %d %d %d\n", nRoute, dist[dest], mh, mh / (mnNode - 1));
    for (int i = mnNode - 1; i >= 1; i--) {
        printf("%s->", name[mRoute[i]]);
    }
    printf("%s", name[mRoute[0]]);

    return 0;
}

1086. Tree Traversals Again 中序遍历的逆向,后序遍历

给了一堆做中序遍历时的 push 和 pop 的命令,要求输出后续遍历。

先从操作逆推了一棵树。写中序遍历的时候,对左孩子入栈,一直到没有左孩子为止,然后出栈后找右孩子。因此找到了规律,如果操作是 push,那下一步准备插入的位置就是它的左子树(如果下一步不是 push 就算了);如果 pop 了一个,那么下一步准备插入的位置是它的右子树。逻辑想了半天,写起来很简单。

恰好节点的 key 都是 1-N的,我就不开树了,直接拿几个数组存下来,免得还得根据 key 查找节点的位置,多麻烦。

最后做一个后序遍历,很简单,过了。

1085. Perfect Sequence

很简单的逻辑,简单到我有点不会做了,卡了半天。

1084. Broken Keyboard

也很简单,按照顺序比对字符就可以了。注意指针怎么向后挪。记一下缺少的键是否输出过了。

1083. List Grades 过于简单

结构体,排个序,输出。本来以为肯定超时,结果case也很弱……

1082 read number in Chinese 复杂逻辑

给出不多于9位的数字,要输出汉语读法。刚开始的思路是每4位读一下,最后结合到一起,结果发现逻辑太复杂了,前面0,后面0,中间两个0,写得很晕。

最终的写法是,先识别不同位置的 0,该跳过还是读一次。标记完 0 之后就很简单了,打表输出。贴代码如下:

# include <cstdio>
# include <cstring>

char digits[10][6] = { "ling ", "yi ", "er ", "san ", "si ", "wu ", "liu ", "qi " , "ba ", "jiu " };
char pos[9][6] = { "", "Qian ", "Bai ", "Shi ", "", "Qian ", "Bai ", "Shi ", "" };
char result[9][20];
char num[11];
int len;

int main() {
    scanf("%s", num);
    if (num[0] == '-') {
        printf("Fu ");
        for (int i = 0; num[i] != '\0'; i++) {
            num[i] = num[i + 1];
        }
    }
    len = strlen(num);

    int i = 0;
    while (num[i] == '0' && i < len) { //刚开始的0要跳过
        num[i] = 's'; //skip
        i++;
    }
    int start = i; //除去0后数字真正开始的地方
    i = len - 1;
    while (num[i] == '0' && i >= 0) { //最后的0也跳过
        num[i] = 's';
        i--;
    }
    i = len - 5;
    while (num[i] == '0' && i >= 0) { //万位及之前相邻的跳过
        num[i] = 's';
        i--;
    }
    i = 0;
    while (i < len) { //其它地方连0都读一个0
        if (num[i] == '0') {
            num[i] = 'r'; //read
            i++;
            while (num[i] == '0' && i < len) {
                num[i] = 's';
                i++;
            }
        }
        i++;
    }

    char read[200] = "";
    for (i = 0; i < len; i++) {
        if (num[i] >= '1' && num[i] <= '9') {
            strcat(read, digits[num[i] - '0']);
            strcat(read, pos[i + 9 - len]);
        }
        else if (num[i] == 'r') {
            strcat(read, digits[0]);
        }
        if (i >= start && i + 9 - len == 0) { //到了亿位
            strcat(read, "Yi ");
        }
        if (i >= start && i + 9 - len == 4) { //到了万位
            strcat(read, "Wan ");
        }
    }
    
    if (strlen(read) == 0) { //输入的是0
        strcpy(read, "ling");
    }
    else {
        read[strlen(read) - 1] = '\0';
    }
    

    printf("%s", read);
    return 0;
}

//Fu yi ba er jiu san Yi si Qian wu Bai liu Shi qi Wan ba Qian jiu Bai
//Fu yi Yi er Qian san Bai si Shi wu Wan liu Qian qi Bai ba Shi jiu

1081. Rational Sum 简单

和 1088 的要求很相似,甚至还变简单了。刚开始跑出了浮点错误,后来看论坛发现是 gcd() 里面没有判断有 0 的情况,有 0 直接返回 1 就可以了。

1079. Total Sales of Supply Chain 超时

题目很简单,一棵树,最后需要一些节点的深度。刚开始我是用 bfs 把所有节点的深度记了一遍,发现超时严重;后来改成需要哪个的深度,就递归往爹娘求,一直求到根节点。结果还是有一个case超时。我把后面需要用的 pow(x, y) 打表了一遍,那个case还是超时。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,594评论 18 139
  • 树的概述 树是一种非常常用的数据结构,树与前面介绍的线性表,栈,队列等线性结构不同,树是一种非线性结构 1.树的定...
    Jack921阅读 4,432评论 1 31
  • 01 第一次打开简书,是为了向朋友们推荐天禅映画,没想它却成了我的另一个兴趣爱好,或者更准确的说,它开启了另一种表...
    映灵77阅读 357评论 0 2
  • 刚刚参加工作的时候,坐在师父后面,盯着玻璃橱窗看了会儿,脱口问道:“这个玻璃,真的防弹吗?” 后来自己坐柜,试着探...
    橙光雨露阅读 360评论 0 0
  • 你的部落现在或将来将面临什么问题?它们的解决方法又是什么?宝爹分享的这篇干货文章基本都提及到了!所以,今天的问题就...
    Travis理想浩阅读 439评论 0 1