Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

[BFS] Cpp代码+详细注释

Posted by yousiki at 2016-07-26 22:55:48 on Problem 2134
首先,感谢 晴艾 兄的代码帮助我从自己那烂透了得懵逼代码中走出来。

嗯,题意不难读,最好看看英文吧。坑,总还是有的。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:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator