zoukankan      html  css  js  c++  java
  • hdu 4385 Moving Bricks (状态压缩dp 2012 MultiUniversity Training Contest 9 )

    http://acm.hdu.edu.cn/showproblem.php?pid=4385

     状态压缩需要好好理解啊;

    又是一道 状态压缩的题 ,一开始觉的和 poj 的一道题有点像 ,特地先做了一下那个题 再回来做的这道题,结果还是没做出来 这到,最后看了 解题报告:

    题意:

    一个人在搬砖,初始位置在(x0,y0),目的地也是(x0,y0),给你n(n<=20)块砖的位置(xi,yi),规定两点之间时间耗费为欧几里德距离的平方,此人一次可以搬不超过两块砖,

    问你最少的时间花费并给出方案.

    官方题解:

    简单状态DP.

    需要注意的是,由于耗费的时间是路长的平方,所以一次性取两点的代价并不一定比分两次取小.

    每次从building出发

    对于当前状态i和当前未纳入状态的点j

    t = i | (1<<j);

    dp[t] = dp[i] + dist[n][j] + dist[j][n];

    对于未纳入状态t的点k

    p = t | (1<<k);

    dp[k] = dp[i] + dist[n][j] + dist[j][k] + dist[k][n];

    关于取点的输出,可以记录当前状态i的前一状态pre[i],两状态取异或即可.每次出发后会取回1~2点 即(Ai1,Ai2)或Ai1

    由于各点的序号是不相同的,只需要比较每次出发取到的较小的序号.

    将这些点或点对取其中序号较小的作为关键字按升序排序输出即可.

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cmath>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<set>
      7 #include<map>
      8 #include<queue>
      9 #include<vector>
     10 #include<string>
     11 #define Min(a,b) a<b?a:b
     12 #define Max(a,b) a>b?a:b
     13 #define CL(a,num) memset(a,num,sizeof(a));
     14 #define maxn  30
     15 #define eps  1e-8
     16 #define inf 100000000
     17 #define N  4000000
     18 #define ll   __int64
     19 using namespace std;
     20 struct node
     21 {
     22     int x;
     23     int y;
     24 }a[maxn] ,ans[maxn];
     25 int cmp(node a,node b)
     26 {
     27     return a.x < b.x;
     28 }
     29 int dp[N] ,dis[maxn][maxn],pre[N];
     30 int main()
     31 {
     32     int i,j,n,t,tmp,p,tp,k,x,y;
     33     int cas = 0 ;
     34     //freopen("data.txt","r",stdin);
     35     scanf("%d",&t);
     36     while(t--)
     37     {
     38         scanf("%d%d",&x,&y);
     39         scanf("%d",&n);
     40         a[n].x = x;
     41         a[n].y = y;
     42         for(i = 0;i< n;i++)
     43         {
     44             scanf("%d%d",&a[i].x,&a[i].y);
     45         }
     46         for(i = 0; i <=n;i++)
     47         {
     48             for(j = i+1;j<=n;j++)
     49             {
     50                 dis[i][j] = dis[j][i] = (a[i].x - a[j].x)*(a[i].x - a[j].x) + (a[i].y - a[j].y)* (a[i].y - a[j].y);
     51             }
     52         }
     53         memset(dp,0x3f,sizeof(dp));
     54         dp[0] = 0 ;
     55         int stat = (1<<n) - 1;
     56         for(i = 0 ; i <= stat ;i++)
     57         {
     58             for(j = 0 ; j<n;j++)
     59             {
     60                 if(!(i&(1<<j)))
     61                 {
     62                     tp = i|1<< j;
     63                     tmp = dp[i] + 2*dis[j][n];
     64                     if(dp[tp] > tmp)
     65                     {
     66                         dp[tp] = tmp;
     67                         pre[tp] =  i;
     68                     }
     69 
     70                    for(k = 0 ; k< n;k++)//如果 一次 去两块
     71                    {
     72                        if(!(tp&(1<<k)))
     73                        {
     74                            p = tp|1<<k;
     75                            tmp = dp[i] + dis[j][n] + dis[j][k] + dis[k][n] ;
     76                            if(dp[p] > tmp)
     77                            {
     78                                dp[p] = tmp;
     79                                pre[p] = i;// 注意 这里的状态 是记录 去两块 之前的 i 
     80                            }
     81                        }
     82                    }
     83                 }
     84             }
     85 
     86         }
     87            printf("Case %d:\n",++cas);
     88             printf("%d\n",dp[stat]);
     89             int t = stat;
     90             int num = 0;
     91 
     92             while(t)
     93             {
     94                 bool flag = false ;
     95                 int tmp = t^pre[t];
     96                 ans[num].y = 25 ;//用来记录一次 取两个 个的第二个元素  (25 表示初始化 没有)
     97                 for(i = 0 ; i < n;i++)
     98                 {
     99                     if((tmp>>i)&1)
    100                     {
    101                         if(!flag)
    102                         {
    103                             ans[num].x = i;
    104                             flag = true ;
    105                         }
    106                         else  ans[num].y = i;
    107                     }
    108                 }
    109 
    110                 t = pre[t];
    111                 num ++;
    112             }
    113 
    114             sort(ans,ans+num,cmp);
    115 
    116 
    117             for(i = 0 ; i< num;i++)
    118             {
    119                 if(i == 0)printf("%d",ans[i].x + 1);
    120                 else printf(" %d",ans[i].x + 1);
    121 
    122                 if(ans[i].y < 25) printf(" %d",ans[i].y + 1) ;
    123             }
    124             puts("");
    125 
    126 
    127 
    128 
    129     }
    130 }
     

     

  • 相关阅读:
    eNSP进行配置网络模拟网络联通
    Labview上使用mydaq采集数据
    Labview实现计算器
    matlab小记(四)
    matlab小记(三)
    matlab小记(二)
    matlab小记(一)
    Python中map和reduce
    Python 如何调用自定义函数
    《机电传动控制》第十一周作业(二)
  • 原文地址:https://www.cnblogs.com/acSzz/p/2651513.html
Copyright © 2011-2022 走看看