hdu 5067 Harry And Dig Machine
http://acm.hdu.edu.cn/showproblem.php?pid=5067
思路:问题可以转化成:从某一点出发,遍历网格上的一些点,每个点至少访问一次需要的最小时间是多少。这就是经典的旅行商问题,考虑到我们必须要遍历的点只有不到10个,可以用状态压缩解决。
dp[i][j]表示i状态的点被访问过了,当前停留在点j 需要的最少时间,状态转移方程:dp[i|(1<<k)][k]=min(dp[i|(1<<k)][k],dp[i][j]+abs(q[j].x-q[k].x)+abs(q[j].y-q[k].y));
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <algorithm> 5 using namespace std; 6 const int inf=1<<30; 7 8 int n,m; 9 int g[100][100]; 10 int dp[1<<11][100]; 11 struct node 12 { 13 int x,y; 14 }st; 15 16 int main() 17 { 18 while(scanf("%d%d",&n,&m)!=EOF) 19 { 20 vector<node>q; 21 for(int i=1; i<=n; i++) 22 { 23 for(int j=1; j<=m; j++) 24 { 25 scanf("%d",&g[i][j]); 26 if(i==1&&j==1) 27 { 28 st.x=i; 29 st.y=j; 30 q.push_back(st); 31 } 32 else if(g[i][j]) 33 { 34 st.x=i; 35 st.y=j; 36 q.push_back(st); 37 } 38 } 39 } 40 int x=q.size(); 41 for(int i=0; i<(1<<x); i++) 42 { 43 for(int j=0; j<x; j++) 44 { 45 dp[i][j]=inf; 46 } 47 } 48 dp[0][0]=0; 49 for(int i=0; i<(1<<x); i++) 50 { 51 for(int j=0; j<x; j++) 52 { 53 for(int k=0; k<x; k++) 54 { 55 if((i&(1<<k))) continue; 56 dp[i|(1<<k)][k]=min(dp[i|(1<<k)][k],dp[i][j]+abs(q[j].x-q[k].x)+abs(q[j].y-q[k].y)); 57 } 58 } 59 } 60 printf("%d\n",dp[(1<<x)-1][0]); 61 } 62 return 0; 63 }
Dp[i|(1≪k)][k]=min(Dp[i|(1≪k)][k],Dp[i][j]+Dis(j,k))