给你一个地图,问你吧所有的隧道都走完的最小费用,起点不固定,穿越隧道的时间不计,在隧道外边每移动一步花费一秒。
思路:
先bfs求出所有dis[i][j](i的终点和j的起点的距离),然后在dp[i][j],i表示当
前状态(二进制压缩后的状态)j表示第几个点,则更新的方程也很简单
dp[i|(1<<(k-1))][j] = minn(本身,dp[i][j] + dis[j][k]);记得要加一个if((i|(1<<(k-1))) == 0)我个人认为没必要加,结果不加就wa,现在还在研究中,记得这种题目之前
做过很多,但之前的数据都很小,可以直接n!,写个搜索或者全排列暴力枚举过去,今天的这个过不去只能用dp了,之前没想过dp因为自己dp很水,想题很少会往dp上想,以后要加强了.
#include<stdio.h> #include<string.h> #include<queue> #define INF 1000000000 using namespace std; typedef struct { int sx ,sy ,ex ,ey; }SD; typedef struct { int x, y ,t; }NODE; SD sd[18]; NODE xin ,tou; int dis[18][18]; char map[18][18]; int mark[18][18]; int dp[(1<<15)+10][18]; int dir[4][2] = {0 ,1 ,0 ,-1 ,1 ,0 ,-1 ,0}; bool ok(NODE a ,int n) { return a.x >= 1 && a.x <= n && a.y >= 1 && a.y <= n && !mark[a.x][a.y] && map[a.x][a.y] == '.'; } int minn(int x ,int y) { return x < y ? x : y; } int bfs(int sx ,int sy ,int ex ,int ey ,int n) { memset(mark ,0 ,sizeof(mark)); xin.x = sx ,xin.y = sy ,xin.t = 0; mark[sx][sy] = 1; queue<NODE>q; q.push(xin); while(!q.empty()) { tou = q.front(); q.pop(); if(tou.x == ex && tou.y == ey) return tou.t; for(int i = 0 ;i < 4 ;i ++) { xin.x = tou.x + dir[i][0]; xin.y = tou.y + dir[i][1]; xin.t = tou.t + 1; if(ok(xin ,n)) { mark[xin.x][xin.y] = 1; q.push(xin); } } } return INF; } int main () { int n ,m ,i ,j ,k; while(~scanf("%d %d" ,&n ,&m)) { getchar(); for(i = 1 ;i <= n ;i ++) { for(j = 1 ;j <= n ;j ++) scanf("%c" ,&map[i][j]); getchar(); } for(i = 1 ;i <= m ;i ++) { scanf("%d %d %d %d" ,&sd[i].sx ,&sd[i].sy ,&sd[i].ex ,&sd[i].ey); for(j = i ;j <= m ;j ++) dis[i][j] = dis[j][i] = INF; } for(i = 1 ;i <= m ;i ++) for(j = i ;j <= m ;j ++) { if(i == j) { dis[i][j] = 0; continue; } dis[i][j] = bfs(sd[i].ex ,sd[i].ey ,sd[j].sx ,sd[j].sy ,n); dis[j][i] = bfs(sd[j].ex ,sd[j].ey ,sd[i].sx ,sd[i].sy ,n); } for(i = 0 ;i <= (1 << m) ;i ++) for(j = 0 ;j <= m ;j ++) dp[i][j] = INF; for(i = 1 ;i <= m ;i ++) dp[1 << (i - 1)][i] = 0; for(i = 0 ;i < (1 << m) ;i ++) for(j = 1 ;j <= m ;j ++) //if(dp[i][j] != INF) for(k = 1 ;k <= m ;k ++) if(!(i & (1 << (k - 1))))//***** dp[i|(1<<(k-1))][k] = minn(dp[i|(1<<(k-1))][k] ,dp[i][j] + dis[j][k]); int ans = INF; for(i = 1 ;i <= m ;i ++) ans = minn(ans ,dp[(1<<m) - 1][i]); ans == INF ? puts("-1") : printf("%d " ,ans); } return 0; }