Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
[BFS] Cpp代码+详细注释首先,感谢 晴艾 兄的代码帮助我从自己那烂透了得懵逼代码中走出来。 嗯,题意不难读,最好看看英文吧。坑,总还是有的。haha~~~ 然后,大致就是BFS了,状态是三维的,转移稍微恶心,细节很重要。 最后,上好的代码,请品尝吧! #include<queue> #include<bitset> #include<cstdio> #include<cstdlib> using namespace std; char in[500000], *p = in; // 读入优化 之 文本读入模式 Orz Seter inline int getInt(void) { // 读入优化 之 读入一个非负整数 int x = 0; while (*p > '9' || *p < '0')p++; while (*p <= '9'&&*p >= '0')(x *= 10) += *p++ - '0'; return x; } inline bool getChr(void) { // 读入优化 之 读入“红和绿” while (*p != 'G'&&*p != 'R')p++; return *p++ == 'G'; } const int INF = 0x3f3f3f3f; // 全局常量 之 正无穷 struct Light { // 结构体 之 红绿灯 int grn, rad, chg; bool fst, has; // 分别表示 绿灯时间 红灯时间 初始时间(见题意) 初始颜色(0是红,1是绿) 是否有灯 void read(void) { // 读入一个红绿灯的信息 grn = getInt(), rad = getInt(), fst = getChr(), chg = getInt(); has = true; // 把当前位置标记为有灯,防止之后的误判 } }light[105]; // light[i]即位置i上的红绿灯 不一定每个位置都有灯,这要看has变量 inline bool check(Light lt, int tm) { // 检查给定的红绿灯在某个时刻是否是红灯 if (lt.has == false)return false; // 根本就没有这个灯,谈何遇上红灯啊 int tmp = (lt.chg + tm) % (lt.grn + lt.rad); // 总的时间模变换周期 return lt.fst ? tmp >= lt.grn : tmp < lt.rad; //初始是绿灯,运行时间大于等于绿灯时长,则变为红灯 //初始是红灯,运行时间严格小于红灯时长,则还是红灯 } struct Node { // BFS中用到的状态 int pos, spd, tim; // 分别表示位置,速度,用时 }; queue<Node> que; // BFS用到的队列 bitset<305> vis[105][105]; // 记录每个状态是否访问过,防止重复 int L, N, ans; // 全局变量 之 看题意吧 signed main(void) { // 这是主函数 fread(p, 1, 500000, stdin); // 再次 Orz Seter L = getInt(); N = getInt(); // 读入 L N for (int i = 1; i <= N; i++) light[getInt()].read(); // 读入红绿灯信息 que.push(Node{ 0,0,0 }); vis[0][0][0] = true; // BFS初始状态,即起点 while (!que.empty()) { // 愚蠢的人类,感受下伟大的BFS吧! st: Node top = que.front(); que.pop(); // 取出、弹出队首 if (top.pos == L&&top.spd == 1) { // 如果达到了目标,即以速度1到达终点(我们再减一下速就是0了) ans = top.tim; break; } // 记录下答案后直接跳出即可 int newspd = max(0, top.spd - 1); // 向后转移,枚举我们减一下速,注意不能为倒车 int newpos = top.pos + top.spd; // 向后转移,移动到的地方一定,当前位置+速度 if (check(light[top.pos], top.tim) && top.spd) continue; //当前位置是不能改变速度的,如果闯了红灯就败了 for (int i = top.pos + 1; i < newpos; i++)if(check(light[i], top.tim))goto st; //违法的话你就败了 if (!vis[newpos][newspd][top.tim + 1]) // 如果新的状态未访问过,就入队 vis[newpos][newspd][top.tim + 1] = true, que.push(Node{ newpos,newspd,top.tim + 1 }); if (!vis[newpos][++newspd][top.tim + 1]) // 这是不改变速度的情况 vis[newpos][newspd][top.tim + 1] = true, que.push(Node{ newpos,newspd,top.tim + 1 }); if (!vis[newpos][++newspd][top.tim + 1])if(newspd<=top.spd+1) // 这是加速的情况,注意不要因为之前的"不倒车"而超速 vis[newpos][newspd][top.tim + 1] = true, que.push(Node{ newpos,newspd,top.tim + 1 }); } printf("%d\n",ans); // 终于可以输出答案了,快哉快哉 } Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator