Clear All of Them I(HDU 3920状压dp)

题意:给有2*n个敌人的位置,枪在(0,0)位置,一次能消灭两个敌人,耗费能量为枪到一个敌人,由这个敌人再到另个敌人的的距离和,求消灭所有敌人最小耗费能量。

分析:一次枚举状态的两位即可

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <cctype>
#include <complex>
#include <cassert>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
#define lson l,m,rt<<1
#define pi acos(-1.0)
#define rson m+1,r,rt<<11
#define All 1,N,1
#define read freopen("in.txt", "r", stdin)
#define N 1<<20
const ll  INFll = 0x3f3f3f3f3f3f3f3fLL;
const int INF= 0x7ffffff;
const int mod =  1000000007;
double dp[N],d[150][150];
int n;
struct point{
    double x,y;
}p[25],s;
double dis(point a,point b){
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int main()
{
    int t,n;
    scanf("%d",&t);
   for(int e=1;e<=t;++e)
    {
        int i,j,k;
        scanf("%lf%lf",&s.x,&s.y);
        scanf("%d",&n);
        for(i=0;i<2*n;i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        for(i=0;i<2*n;i++)
        {
            d[i][2*n]=dis(s,p[i]);
            for(j=0;j<2*n;j++)
                d[i][j]=d[j][i]=dis(p[i],p[j]);
        }
        int cas=(1<<(2*n))-1;
        for(i=0;i<=cas;i++)
            dp[i]=INF;
        dp[0]=0;
        for(i=0;i<=cas;i++){
            if(dp[i]==INF)continue;
                for(j=0;j<2*n;j++)
                    if((i&(1<<j))==0)
                        break;
                for(k=j+1;k<2*n;k++)
                {
                    if(i&(1<<k))
                        continue;
                    double tmp=min(d[j][2*n],d[k][2*n]);
                    tmp+=d[j][k];
                    int tcase=i+(1<<j)+(1<<k);
                    dp[tcase]=min(dp[tcase],dp[i]+tmp);
                }
        }
        printf("Case #%d: %.2lf\n",e,dp[cas]);
    }
    return 0;
}

  

posted on 2015-07-24 21:40  积跬步、至千里  阅读(149)  评论(0编辑  收藏  举报

导航