8.30 日志

题目 – luoguP1139

考虑暴搜,不停尝试A到B、A到C、A到D、B到C、B到D、C到D,尝试顺序正好是按照字典序。但暴搜会炸,发现总的操作次数最少为$n$(每辆火车直接A到D),最多为$3n$(每辆火车都A到B、B到C、C到D),于是类似迭代加深搜索地去限制总的操作次数进行搜索,遇到可行的方案就输出答案后强制exit。还要加一些可行性剪枝,不然会TLE。

void dfs(int k, int m){
	if(k > m){
		if(cnt[3] < n) return ; // 已经操作了m次却还没调度完
		for(auto v : ans){
			cout << (char)(v.h + 'a') << ' ';
			cout << (char)(v.l + 'A') << ' ';
			cout << (char)(v.r + 'A') << '\n';
		}
		exit(0); // 强制exit
	}
	if(cnt[3] && a[3][cnt[3]] != s[n - cnt[3]] - 'a') return ; // D处顺序有硬性要求,一处不对就剪掉
	if(m - k + 1 < cnt[0] + cnt[1] + cnt[2]) return ; // 剩下的即使都直接向D处移,剩余操作次数也不够了
	for(int i = 0; i <= 2; i++){ // 0-A, 1-B, 2-C
		if(!cnt[i]) continue; // i处没有火车,也就不用调度
		for(int j = i + 1; j <= 3; j++){ // 只能从左向右单向开
			a[j][++cnt[j]] = a[i][cnt[i]--]; // i -> j
			ans.push_back({a[j][cnt[j]], i, j}); // 存操作
			dfs(k + 1, m);
			a[i][++cnt[i]] = a[j][cnt[j]--]; // j -> i 回溯
			ans.pop_back(); // 回溯操作
		}
	}
}
int main(){
	cin >> n >> s;
	for(int i = 0; i < n; i++) a[0][++cnt[0]] = i; // 一开始A-0处有火车a-0, b-1, c-2...
	for(int i = n; i <= 3 * n; i++) dfs(1, i);
	cout << "NO\n"; // 没有方案
	return 0;
}

后话

迭代加深搜索 + 可行性剪枝,提高组级别的dfs题。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇