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
",dp[(1<<x)-1][0]);
61      }
62      return 0;
63 }
View Code

Dp[i|(1k)][k]=min(Dp[i|(1k)][k],Dp[i][j]+Dis(j,k))
原文地址:https://www.cnblogs.com/fanminghui/p/4326217.html