hdu 3681 压缩dp+搜索
题意:一个机器人想越狱,他只能带一定电量的电池,'S'表示道路可行,'G'表示充电器, 只可充电一次,但是可以经过很多次。'F'表示起点,'Y'表示要破坏的机关,也是只能破坏一次,但是可以经过无数次。'D'表示不能经过的地点。求他能 破坏所有机关,带的最小初始电量。
链接:点我
真是神烦无比啊啊,这题
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 const int INF=0x3f3f3f3f; 11 const double eps=1e-5; 12 typedef long long ll; 13 #define cl(a) memset(a,0,sizeof(a)) 14 #define ts printf("*****\n"); 15 const int MAXN=17; 16 int n,m,tt; 17 int d[4][2]={0,1,0,-1,1,0,-1,0}; 18 int dp[1<<MAXN][MAXN]; 19 char s[MAXN][MAXN]; 20 int dist[MAXN][MAXN][MAXN][MAXN]; 21 int cnt; 22 int start; 23 int fin=0; 24 bool vis[MAXN][MAXN]; 25 struct Node 26 { 27 int x,y; 28 }node[MAXN],st,ed; 29 void bfs(int x,int y) //x,y点到其他点的距离 30 { 31 cl(vis); 32 if(s[x][y]=='D')return;//这个点的不需要处理 33 queue<Node> q; 34 for(int i=0;i<n;i++) 35 { 36 for(int j=0;j<m;j++) 37 { 38 dist[x][y][i][j]=-1; 39 } 40 } 41 while(!q.empty()) q.pop(); 42 Node now,next; 43 now.x=x,now.y=y; 44 dist[x][y][x][y]=0; 45 q.push(now); 46 vis[x][y]=1; 47 while(!q.empty()) 48 { 49 now=q.front(); 50 q.pop(); 51 for(int i=0;i<4;i++) 52 { 53 next.x=now.x+d[i][0]; 54 next.y=now.y+d[i][1]; 55 if(!vis[next.x][next.y]&&next.x>=0&&next.x<n&&next.y>=0&&next.y<m&&s[next.x][next.y]!='D') 56 { 57 if(dist[x][y][next.x][next.y]!=-1)continue; 58 dist[x][y][next.x][next.y]=dist[x][y][now.x][now.y]+1; 59 q.push(next); 60 vis[next.x][next.y]=1; 61 } 62 } 63 } 64 } 65 bool check(int v) 66 { 67 memset(dp,-1,sizeof(dp)); 68 dp[1<<start][start]=v; 69 for(int i=0;i<(1<<cnt);i++) 70 for(int j=0;j<cnt;j++) 71 { 72 if(i==j) continue; 73 if((i&(1<<j))==0) continue; //去过了 74 if(dp[i][j]==-1)continue; 75 if((i&fin)==fin) return 1; 76 for(int k=0;k<cnt;k++) 77 { 78 if((i&(1<<k))) continue; 79 int dis=dist[node[j].x][node[j].y][node[k].x][node[k].y]; 80 if(dis==-1||dp[i][j]<dis) continue; 81 dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],dp[i][j]-dis); 82 if(s[node[k].x][node[k].y]=='G')dp[i|(1<<k)][k]=v; 83 } 84 } 85 return 0; 86 } 87 int main() 88 { 89 int i,j,k; 90 #ifndef ONLINE_JUDGE 91 freopen("1.in","r",stdin); 92 #endif 93 while(scanf("%d%d",&n,&m)!=EOF) 94 { 95 if(n==0&&m==0) break; 96 for(i=0;i<n;i++) scanf("%s",s[i]); 97 for(i=0;i<n;i++) 98 { 99 for(j=0;j<m;j++) 100 { 101 bfs(i,j); 102 } 103 } 104 cnt=0; 105 fin=0; 106 for(i=0;i<n;i++) 107 { 108 for(j=0;j<m;j++) 109 { 110 if(s[i][j]=='F') 111 { 112 start=cnt; 113 fin|=(1<<cnt); 114 node[cnt].x=i; 115 node[cnt++].y=j; 116 } 117 else if(s[i][j]=='Y') 118 { 119 fin|=(1<<cnt); 120 node[cnt].x=i; 121 node[cnt++].y=j; 122 } 123 else if(s[i][j]=='G') 124 { 125 node[cnt].x=i; 126 node[cnt++].y=j; 127 } 128 } 129 } 130 int l=0; 131 int r=n*m; 132 int ans=-1; 133 while(l<=r) 134 { 135 int mid=(l+r)>>1; 136 if(check(mid)) 137 { 138 ans=mid; 139 r=mid-1; 140 } 141 else l=mid+1; 142 } 143 printf("%d\n",ans); 144 } 145 }