查看文章 |
PKU 2688[BFS+状态压缩dp/TSP]
2010-10-29 18:30
/*PKU 2688 BFS+状态压缩DP/TSP dp[i][j] 假设j中的二进制位为1的个数为k那些该方程表示,清除了k个dirt,并且根据位表示不同的dirt, 且当前结束时候机器人的位置在第i个dirt上面花费的最少步数,于是状态转移就不难理解了,WA两次,原来是我的INF申明的是int的最大数,再加一个int就成为负数,于是就WA了 */ #include <iostream> #include <queue> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define F(i, s, e) for(int i(s), __(e); i<=__; i++) #define FOR(i, s, e) for(int i(s), __(e); i<__; i++) #define CLR(arr, v) memset(arr, v, sizeof(arr)) #define Debug(v) printf("%d\n", v); #define INF 0x7fffffff #define size 21 int h, w; int direction[4][2]={ {1, 0}, {-1, 0}, {0, 1}, {0, -1} }; char map[size][size]; struct POINT { int x, y, step; POINT( ){ } POINT(int xx, int yy, int s):x(xx),y(yy),step(s){ } }point[size]; int num; bool visit[size][size]; int dist[size][size], getId[size][size]; bool check(int y, int x) { if (y>=1 && y<=h && x>=1 && x<=w && visit[y][x]==false&&map[y][x]!='x') return true; return false; } void BFS(POINT st, int id)//计算st到其它点的最短距离 { POINT cur, next; queue<POINT>Q; Q.push( POINT(st.x, st.y, 0) ); CLR(visit, false); visit[st.y][st.x]=true; while ( !Q.empty( ) ) { cur = Q.front( ); Q.pop( ); FOR(i, 0, 4) { next.y = cur.y + direction[i][0]; next.x = cur.x + direction[i][1]; if (check(next.y, next.x) ) { visit[next.y][next.x]=true; next.step = cur.step + 1; Q.push( next ); if ( map[next.y][next.x]=='o' )//表示到达机器人的起点 { dist[id][1] = dist[1][id]=next.step; }else if( map[next.y][next.x]=='*') //表示脏的地方 { int u = getId[next.y][next.x]; //取得当前点的ID dist[u][id]=dist[id][u]=next.step; } } } } } int dp[11][1<<11]; void solve( ) { int ii; dp[1][0]=0; //1表示机器人的ID,0转化为二进制全部为0,表示清除了0个脏地方 int Bound=(1<<(num-1))-1; F(i, 1, Bound) //表示状态 { ii=i; F(j, 0, num-2) //j位 { if ( (ii&(1<<j) )>=1 ) //判断ii的当前位是否为1 { dp[j+2][i]=INF; // int s=(ii^(1<<j)); //上一个状态 bool tag=false; F(k, 0, num-2) { if ((s&(1<<k))>=1 ) { dp[j+2][i]=min(dp[j+2][i], dp[k+2][s]+dist[j+2][k+2]); tag=true; } } if (!tag) dp[j+2][i]=dist[j+2][1]; //表示的是清除第一个dirt } } } } int main( ) { freopen("in.txt","r",stdin); while (~scanf("%d%d", &w, &h) &&(w||h)) { getchar( ); num=1; F(i, 1, h){ F(j, 1, w) { scanf("%c", &map[i][j]); if (map[i][j]=='o') {point[1].y=i; point[1].x=j; } if (map[i][j]=='*') { point[++num].y=i; point[num].x=j; getId[i][j]=num; } } getchar( ); } F( i, 1, num ) F(j, 1, num) dist[i][j]=INF; //下面BFS计算两两点之间的距离 //Debug(point[1].y); Debug(point[1].x); BFS(point[1], 1); FOR(i, 2, num) BFS(point[i], i); bool mark=false; F( i, 2, num) if (dist[1][i]==INF) { mark=true; break; } if (mark) { puts("-1"); continue; } /*F(i, 1, num) { F(j, 1, num) printf("%d ", dist[i][j]); putchar('\n'); }*/ //两两点的距离计算完之后再用状态DP solve( ); int ret=INF; if (num==1){ puts("0"); continue; } F(i, 2, num) { ret = min(ret, dp[i][(1<<(num-1))-1]); } if (ret<INF) printf("%d\n", ret); else puts("-1"); } return 0; } |
最近读者:

