HDU 4385 Moving Bricks【状态压缩DP】

题意: 有 n 个砖块,知道了每个砖块的位置和人的起始位置 st,现在要把这 n 块砖搬到st,每次最多能搬回两块砖,搬砖块的体力耗费为两个地点距离的平方,

         问搬回这 n 块砖所需消耗的最小体力是多少,并按字典序输出搬砖块的顺序。

分析: dp[i] 表示 i 状态的最小值

         dp[i] = max(dp[i],dp[i |(1<<j)]+2*dis[n][j])                                      搬一块砖的时候

         dp[i] = max(dp[i],dp[i|(1<<j)|(1<<k)]+dis[n][j]+dis[j][k]+dis[n][k])   搬两块砖的时候

        同时用pre[] 记录状态转移路径

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define clr(x)memset(x,0,sizeof(x))
#define min(a,b)(a)<(b)?(a):(b)
#define INF 0x1f1f1f1f
#define N 21
struct node
{
    int x,y;
}p[N],begin;
int dis(node a,node b)
{
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
int g[N][N];
int dp[1<<N];
int pre[1<<N];
struct ans
{
    int fi,se,num;
}res[N];
bool cmp(ans a,ans b)
{
    return a.fi<b.fi;
}
int main()
{
    int ca=1,n,i,j,k,t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&begin.x,&begin.y);
        scanf("%d",&n);
        p[n]=begin;
        for(i=0;i<n;i++)
            scanf("%d%d",&p[i].x,&p[i].y);
        memset(dp,INF,sizeof(dp));
        pre[0]=0;
        int st=1<<n;
        dp[0]=0;
        for(i=0;i<=n;i++)
            for(j=0;j<=n;j++)
                g[i][j]=dis(p[i],p[j]);
        printf("Case %d:\n",ca++);
        int stat,tmp,ss;
        for(i=0;i<st;i++)
        {
            for(j=0;j<n;j++)
            {
                if((1<<j)&i)
                    continue;
                stat=i|(1<<j);
                tmp=dp[i]+g[n][j]*2;
                if(tmp<dp[stat])
                {
                    dp[stat]=tmp;
                    pre[stat]=i;
                }
                for(k=j+1;k<n;k++)
                {
                    if((1<<k)&i)
                        continue;
                    ss=stat|(1<<k);
                    tmp=dp[i]+g[n][j]+g[j][k]+g[n][k];
                    if(tmp<dp[ss])
                    {
                        dp[ss]=tmp;
                        pre[ss]=i;
                    }
                }
            }
        }
        st-=1;
        printf("%d\n",dp[st]);
        int top=0;
        while(st)
        {
            stat=pre[st]^st;
            st=pre[st];
            res[top].num=0;
            for(i=0;i<n;i++)
                if((1<<i)&stat)
                {
                    res[top].num++;
                    if(res[top].num==1)
                        res[top].fi=i+1;
                    else res[top].se=i+1;
                }
            top++;
        }
        sort(res,res+top,cmp);
        for(i=0;i<top;i++)
        {
            if(res[i].num==1)
                printf("%d%c",res[i].fi,i==top-1?'\n':' ');
            else 
                printf("%d %d%c",res[i].fi,res[i].se,i==top-1?'\n':' ');
        }
    }
    return 0;
}

 

posted @ 2012-10-06 21:05  'wind  阅读(464)  评论(0编辑  收藏  举报