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 }
View Code

 



Dp[i|(1k)][k]=min(Dp[i|(1k)][k],Dp[i][j]+Dis(j,k))

你可能感兴趣的:(mac)