HDU - 5004 KAMI(回溯+dfs)
来源:互联网 发布:squid linux 下载 编辑:程序博客网 时间:2024/05/29 10:54
题目大意:
这题的规则和KAMI游戏的规则相同。可以百度一下这个游戏。
规则大概如下:
有一个 16*10 由4种颜色组成的图,你可以用任意一种颜色对这个图上颜色不相同的点进行染色,染色的同时,其周围上的颜色相同的点,也被染色成你要染的颜色。
问你能否用至少n步,将图片染成1中颜色。
解析:
此题给出了最小步数n<=8,显然是限制了dfs的深度,因此就是暴力搜索题。
其实对于每次选择一个点变颜色,等价于每次都对同一个点改变颜色。
因此就可以枚举一个点,然后bfs做出与该点所在的联通块相邻的联通块都有哪些颜色,基于本体联通块的定义,这些颜色必定不同于该点的颜色,然后枚举要把该点变成那些颜色,然后bfs染色,继续搜索就可以了。
最终当图被染成一种颜色,则结束搜索。
总结:这题比较难,记得当时网络赛,好像没人能做出来,对于每次选择一个点变颜色,等价于每次都对同一个点改变颜色。
这题的规则和KAMI游戏的规则相同。可以百度一下这个游戏。
规则大概如下:
有一个 16*10 由4种颜色组成的图,你可以用任意一种颜色对这个图上颜色不相同的点进行染色,染色的同时,其周围上的颜色相同的点,也被染色成你要染的颜色。
问你能否用至少n步,将图片染成1中颜色。
解析:
此题给出了最小步数n<=8,显然是限制了dfs的深度,因此就是暴力搜索题。
其实对于每次选择一个点变颜色,等价于每次都对同一个点改变颜色。
因此就可以枚举一个点,然后bfs做出与该点所在的联通块相邻的联通块都有哪些颜色,基于本体联通块的定义,这些颜色必定不同于该点的颜色,然后枚举要把该点变成那些颜色,然后bfs染色,继续搜索就可以了。
最终当图被染成一种颜色,则结束搜索。
总结:这题比较难,记得当时网络赛,好像没人能做出来,对于每次选择一个点变颜色,等价于每次都对同一个点改变颜色。
这个方法实在是太难想了,但是我又很想把这题给做出来,因为觉得KAMI这个游戏很有趣,于是上网搜索了大神的题解,照着他的思路敲了一遍。
#include <cstdio>#include <cstring>#include <queue>using namespace std;const int ROW = 16;const int COL = 10;const int dr[] = {-1, 0, 1, 0};const int dc[] = { 0, 1, 0,-1};struct Node {int r,c;Node() {}Node(int _r,int _c) {r = _r;c = _c;}};int n; //最小步数bool ok;char grid[ROW+1][COL+1];int ans[ROW*COL];bool full() {for(int i = 1; i <= ROW; i++) {for(int j = 1; j <= COL; j++) {if(grid[i][j] != grid[1][1]) {return false;}}}return true;}void dfs(int x,int y,int cur) {char now[ROW+1][COL+1];int vis[ROW+1][COL+1];if(cur == n) {if(full()) {ok = true;}return ;}int color = grid[x][y] - '0';for(int i = 1; i <= 4; i++) { //枚举颜色if(color == i) { //如果要染的颜色和当前的颜色相同,则不要枚举continue;}memset(vis,0,sizeof(vis));memcpy(now,grid,sizeof(grid));//将连通区域进行染色queue<Node> que;que.push(Node(x,y));vis[x][y] = true;int r,c;while(!que.empty()) {Node front = que.front();que.pop();grid[front.r][front.c] = i + '0';for(int d = 0; d < 4; d++) {r = front.r + dr[d];c = front.c + dc[d];if(grid[r][c] - '0' != color || vis[r][c]) {continue;}vis[r][c] = true;que.push(Node(r,c));}}ans[cur] = i;dfs(x,y,cur+1);if(ok) {return ;}memcpy(grid,now,sizeof(grid));}}void solve() {scanf("%d",&n);memset(grid,0,sizeof(grid));for(int i = 1; i <= ROW; i++) {scanf("%s",grid[i]+1);}for(int i = 1; i <= ROW; i++) {for(int j = 1; j <= COL; j++) {if(grid[i-1][j] == grid[i][j] || grid[i][j-1] == grid[i][j]) {//如果当前点前面连通的点无法覆盖成功,则后面的点就不需要考虑continue;}ok = false;dfs(i,j,0);if(ok) {for(int k = 0; k < n; k++) printf("%d %d %d\n",ans[k],i,j);return;}}}}int main() {int t,cas = 1;scanf("%d",&t);while(t--) {printf("Case #%d:\n",cas++);solve();}return 0;}
0 0
- HDU - 5004 KAMI(回溯+dfs)
- [HDU 5004 KAMI] dfs+bfs
- HDU 5045 Contest(DFS 回溯)
- HDU 2589 正方形划分(DFS+回溯)
- HDU 4499 Cannon (DFS回溯)
- HDU 2614 Beat(dfs+回溯)
- hdu 1045 DFS+回溯
- HDU 1015 dfs回溯
- hdu 1045 DFS回溯
- HDU 1016 dfs+回溯
- hdu 1016 dfs+回溯
- 希望(kami)
- kami
- HDU 1242 Rescue - DFS 回溯
- HDU 1015 爆搜 /dfs+回溯
- HDU 1181 DFS回溯思想
- HDU 1015 safecraker (DFS 回溯)
- hdu 2616 dfs回溯暴力
- 几门编程语言的学习网站
- (转)mysql 错误1175
- html+css基础(续)
- (原)mysql错误1093 You can't specify target table 'wms_cabinet_form' for update in FROM clause
- vim设置背景颜色
- HDU - 5004 KAMI(回溯+dfs)
- 升级docker到1.3
- 团队协作之AAR(任务后检视方法)
- 使用VS2010开发ActiveX(MFC)控件(3)——添加接口及WEB调用
- 利用开源组件commons-fileupload上传图片文件(2)
- Android很全常用工具类源码
- php实现简单验证码
- 学习GCD后感——转自海森v
- 双向循环链表基本操作(C语言)