zoj 3611 Ice Valley 状压BFS
来源:互联网 发布:miss的淘宝店网址 编辑:程序博客网 时间:2024/06/06 00:38
500*500的平面,每格都有一个标记,表及含义如下:
标记:0 空白位置,在此处可以向上下左右四个方向走,保证0位置不超过100个。
标记:# 陷阱,走到此处会挂掉
标记:W 墙,这个位置不能走
标记:$ 盒子,在此处可以花费2秒打开盒子,取走钱,之后可以向上下左右四个方向走,保证$位置不超过10个。
标记:U,D,L,R 分别对应上下左右,在这个标记处,下一步只能按照标记的方向走。
由于0和$最多只有110个,所以可以把这些可以自由行动的点抽出来,重新建成一个图,也就是对原矩阵预处理一下。首先给这些点标下号,$在前(方便装压记录取钱情况)0在后,然后遍历矩阵,遍历到一个$或0时,枚举四个方向,看最近可以到达哪个$或0,同时记录话费,建成一个新图。预处理后就从起点开始BFS了,Dp[x][sta]表示在x节点,取钱状态为sta时的最小时间,每次扩展出一个新节点v时,若时间ti>dp[v][sta]就更新Dp的值,并且若v,sta这对状态没有在队列中就让它进队(类似SPFA)。最后便利一下dp[ed]的所有状态,找一个1最多的对应的时间输出就行了。
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <queue>using namespace std;typedef long long ll;const int fx[4]={0,1,0,-1};const int fy[4]={1,0,-1,0};struct EG{ int v,next,w;}edge[42000];int en;int g[220];const int inf=9999999;char s[550][550];int num[550][550];int n,m,p,q,x,y,z,k;int numa,numb;bool vis[550][550];bool check(int x,int y){ if (x>0 && x<=n && y>0 && y<=m && s[x][y]!='W' && s[x][y]!='#') { return true; } return false;}int trans(int x,int y,int &t){ memset(vis,false,sizeof vis); while(s[x][y]!='0' && s[x][y]!='$') { t++; if (s[x][y]=='L') y--; else if (s[x][y]=='R') y++; else if (s[x][y]=='U') x--; else if (s[x][y]=='D') x++; if (vis[x][y]) return -1; if (!check(x,y)) return -1; vis[x][y]=true; } return num[x][y];}int sx,sy,ex,ey;int dp[220][2048];bool inq[220][2048];struct node{ int id,sta; node() { } node(int x,int y) { id=x; sta=y; }};int calc(int x){ int res=0; while(x) { if (x&1) res++; x>>=1; } return res;}void addedge(int u,int v,int w){ edge[en].v=v; edge[en].w=w; edge[en].next=g[u]; g[u]=en; en++;}int main(){// freopen("in.txt","r",stdin); while(~scanf("%d%d",&n,&m)) { memset(num,-1,sizeof num); numa=numb=0; for (int i=1; i<=n; i++) scanf("%s",&s[i][1]); scanf("%d%d%d%d",&sx,&sy,&ex,&ey); for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) { if (s[i][j]=='$') num[i][j]=numb++; } numa=numb; for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) if (s[i][j]=='0') num[i][j]=numa++; memset(g,-1,sizeof g); en=0; int tx,ty,ti; int u,v; for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) if (num[i][j]!=-1) { u=num[i][j]; for (int k=0; k<4; k++) { tx=i+fx[k]; ty=j+fy[k]; ti=1; if (check(tx,ty)) { v=trans(tx,ty,ti); if (v!=-1) { addedge(u,v,ti); } } } } int st=num[sx][sy]; int ed=num[ex][ey]; queue<node> q; while(!q.empty()) { q.pop(); } memset(dp,0x3f,sizeof dp); q.push(node(st,0)); dp[st][0]=0; inq[st][0]=true; while(!q.empty()) { int u=q.front().id; int v; int sta=q.front().sta; q.pop(); inq[u][sta]=false; int tu,ts,ti; for (int j=g[u]; j!=-1; j=edge[j].next) { tu=u; ts=sta; ti=dp[u][sta]; v=edge[j].v; ti+=edge[j].w; if (v<numb) { if (((1<<v)&ts)==0) { ti+=2; ts|=(1<<v); } } if (dp[v][ts]>ti) { dp[v][ts]=ti; if (!inq[v][ts]) { q.push(node(v,ts)); inq[v][ts]=true; } } } } int ans=inf,tt=-1; for (int i=0; i<(1<<numb); i++) { int tmp=calc(i); if (tmp>tt && dp[ed][i]<inf) { ans=dp[ed][i]; tt=tmp; } } if (ans==inf) puts("-1"); else printf("%d\n",ans); } return 0;}
0 0
- zoj 3611 Ice Valley 状压BFS
- ZOJ - 3611——Ice Valley
- ZOJ 3611 BFS+状态压缩
- Ice Cave(BFS)
- hdu 6149 Valley Numer II(状压+ 枚举)
- 【HDU6149】Valley Numer II(状压DP)
- 【Codeforces】C. Ice Cave(bfs)
- CodeForces 540C Ice Cave (BFS)
- CodeForces 540 C Ice Cave (BFS)
- codeforces 540C Ice Cave【BFS】
- Codeforces 540C Ice Cave (BFS)
- cf#301-C. Ice Cave-BFS
- |Tyvj|BFS|P1117 拯救ice-cream
- Ice Cave-CF-C(bfs)
- ZOJ 1649 Rescue (BFS)
- ZOJ 1005 Jugs 【BFS】
- zoj 1438 Asteroids! BFS
- zoj 1649 rescue (bfs)
- awk手册
- C#总结
- Log4J.xml的模板
- POJ 3067 Japan (树状数组)
- 查找算法大集合
- zoj 3611 Ice Valley 状压BFS
- [LeetCode] Single Number
- 项目二。
- node-qunit的测试结果如何显示到浏览器中(1)
- C++基础
- POJ1002 487-3279
- linux中TFTP配置
- SQL常用函数集锦
- 数据结构基础(12)------------Shell排序