hdu4771_2013亚洲区域赛杭州站(状态压缩bfs)
2015-07-28 14:35
429 查看
///////////////////////////////////////////////////////////////////////////////////////////////////////
作者:tt2767
声明:本文遵循以下协议自由转载-非商用-非衍生-保持署名|Creative Commons BY-NC-ND 3.0
查看本文更新与讨论请点击:http://blog.csdn.net/tt2767
链接被删请百度: CSDN tt2767
///////////////////////////////////////////////////////////////////////////////////////////////////////
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4771
这题从中午做到晚上啊,收获还是比较多的。。。
学到的几点:
1.状态压缩:把状态压成二进制,通过查看二进制的每一位来判断状态。
2.带状态的bfs,虽然原来做过一道,但之前是还是不太明白
3.把地图数据化表示很有用
4.自己包装输入
5.。。。。。。。。。。
题解:
先把输入的数据处理一下,记录起点之后,数据化地图:
墙为-1,宝藏为1,2,4,8(二进制就是0001,0010,0100,1000),起点和路都为0.
每次通过加和记录已找到宝藏的状态
eg:找到了2,8记录为10(0010+1000=1010)
可用按位与来判断是否捡过宝藏
宝藏可能在任何地方,如果在墙里面,直接输出-1;
作者:tt2767
声明:本文遵循以下协议自由转载-非商用-非衍生-保持署名|Creative Commons BY-NC-ND 3.0
查看本文更新与讨论请点击:http://blog.csdn.net/tt2767
链接被删请百度: CSDN tt2767
///////////////////////////////////////////////////////////////////////////////////////////////////////
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4771
这题从中午做到晚上啊,收获还是比较多的。。。
学到的几点:
1.状态压缩:把状态压成二进制,通过查看二进制的每一位来判断状态。
2.带状态的bfs,虽然原来做过一道,但之前是还是不太明白
3.把地图数据化表示很有用
4.自己包装输入
5.。。。。。。。。。。
题解:
先把输入的数据处理一下,记录起点之后,数据化地图:
墙为-1,宝藏为1,2,4,8(二进制就是0001,0010,0100,1000),起点和路都为0.
每次通过加和记录已找到宝藏的状态
eg:找到了2,8记录为10(0010+1000=1010)
可用按位与来判断是否捡过宝藏
宝藏可能在任何地方,如果在墙里面,直接输出-1;
#include<string> #include<iostream> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<queue> using namespace std; typedef long long int LL; const int INF = 0x3f3f3f3f ; const long double PI = acos(0.0) * 2.0; const int N = 200; const int dx[]={0,1,0,-1}; const int dy[]={1,0,-1,0}; const int change[] ={0,1,2,4,8}; struct P { int x,y,step,num; P(int x,int y,int step,int num):x(x),y(y),step(step),num(num){} P(){} }; P s; bool vis ; char input ; int maze ; int sum,n,m; bool flag;//是否有宝物在墙里? int bfs(); bool pass(P);//不管走没走过,这个位置是可以走的 bool read(); int main() { while( read() ) printf("%d\n",bfs()); return 0; } int bfs() { if(flag) return -1; //如果在墙里是不可能找全的 memset(vis,0,sizeof(vis)); queue<P> q; vis[s.x][s.y][s.num] = 1; q.push(s); while(!q.empty()) { P p = q.front();q.pop(); if(p.num == sum ) return p.step; for(int i = 0 ; i < 4 ; i++) { P now = p; //先继承上一次的属性 now.x += dx[i]; now.y += dy[i]; if( pass(now) ) { if(maze[now.x][now.y] > 0 ) // 本题关键步骤!! { int mark1 = maze[now.x][now.y]; //宝藏的标记 int mark2 = now.num; //人的标记 if( (mark1&mark2) == 0 ) //按位与判断,如果没捡过此宝藏,就把它捡起来 { now.num += maze[now.x][now.y]; } } if(!vis[now.x][now.y][now.num]) { now.step = p.step + 1; vis[now.x][now.y][now.num] = 1; q.push(now); } } } } return -1; } bool read() { memset(input,'\0',sizeof(input)); memset(maze,0,sizeof(maze)); if(scanf("%d%d",&n,&m) != 2 || !(n+m)) return false; for(int i = 1 ; i <= n ; i++) { getchar(); for(int j = 1 ; j <= m ; j++) { scanf("%c",&input[i][j]); if(input[i][j] == '.') //地图数据化 { maze[i][j] = 0; } else if(input[i][j] == '@') { maze[i][j] = 0; s = P(i,j,0,0); } else { maze[i][j] = -1; } } } sum = 0; flag = false; int k; scanf("%d",&k); for(int i = 1 ; i <= k ; i++) { int x,y; scanf("%d%d",&x,&y); if(maze[x][y] < 0) flag = true; //在墙里的话标记一下 maze[x][y] += change[i]; sum+= maze[x][y]; } return true; } bool pass(P z) { return (0 < z.x && z.x<= n && 0 < z.y && z.y <= m && maze[z.x][z.y] != -1 ); }
相关文章推荐
- 关于openCV getRotationMatrix2D 函数中平移向量的理解
- SSH商城笔记
- maven常用命令
- ibatis之——sqlMapConfig.xml配置文件详解
- iOS多线程的初步研究(三)-- NSRunLoop
- 微信公众平台开发教程第19篇-应用实例之人脸检测
- Factorization Machines 学习笔记(三)回归和分类
- PCIe固态存储和HDD常见的硬盘性能对比测试
- linux文件压缩与打包
- jquery 选择器
- 进程间通信之消息通信
- 64 位 win7 使用PLSQL Developer
- SQL 中varchar,nvarchar,char区别
- Java中Scanner的理解大总结
- NodeJs服务器管理
- java中静态代码块的用法 static用法详解
- 【Android应用开发技术:应用组件】:Activity基本原理
- 《侠客行》——李白
- 七内部排序算法汇总(插入排序、Shell排序、冒泡排序、请选择类别、、高速分拣合并排序、堆排序)
- gclub บนมือถือ 24 ชั่วโมง