| ||||||||||
| 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