HLG 1067 QQ Farm【状态压缩DP】

题意:  用正方形拍子拍蚊子,拍T次,每次至少要拍死一个蚊子,一次拍死N只得N*N点经验,每次每只蚊子的位置不一样,死了的蚊子不记入以后,问最多能得

         多少经验。

分析:  dp[i][j]  表示第 i 次在 j 状态下的最大经验值, 需要求出第 i 次能一次拍死的所有的蚊子组合, 对于每只蚊子需要考虑两种情况:

           ① 刚好被覆盖的情况

           ② 刚好不被覆盖的情况

           可以在原来的坐标加上一个很小的偏移量

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
#define clr(x)memset(x,0,sizeof(x))
#define eps 1e-8
#define INF 0x1f1f1f1f
#define N 11
int dp[N][1<<N];
int num[1<<N];
int v[1<<N];
int pos[1<<N];
double x[N],y[N];
int tot,n;
double R;
int max(int a,int b)
{
    return a>b?a:b;
}
void determin_place()
{
    double xp[100],yp[100];
    clr(v);
    int i,j,k;
    int xt=0,yt=0;
    for(i=0;i<n;i++)
    {
        xp[xt++]=x[i]+eps;   xp[xt++]=x[i];   xp[xt++]=x[i]-eps;
        xp[xt++]=x[i]-R+eps; xp[xt++]=x[i]-R; xp[xt++]=x[i]-R-eps;
        yp[yt++]=y[i]+eps;   yp[yt++]=y[i];   yp[yt++]=y[i]-eps;
        yp[yt++]=y[i]-R+eps; yp[yt++]=y[i]-R; yp[yt++]=y[i]-R-eps;
    }
    sort(xp,xp+xt);
    sort(yp,yp+yt);
    int stat;
    tot=0;
    for(i=0;i<xt;i++)
        for(j=0;j<yt;j++)
        {
            stat=0;
            for(k=0;k<n;k++)
            {
                if(x[k]+eps>xp[i]&&x[k]-eps<xp[i]+R&&
                   y[k]+eps>yp[j]&&y[k]-eps<yp[j]+R)
                   stat|=(1<<k);
            }
            if(!v[stat]&&stat>0)
            {
                pos[tot++]=stat;
                v[stat]=1;
            }
        }
}
int main()
{
    int t,i,j,k;
    while(scanf("%d%d",&n,&t)!=EOF)
    {
        scanf("%lf",&R);
        clr(num);
        int st=1<<n;

        for(i=0;i<st;i++)
            for(k=0;k<n;k++)
                if(i&(1<<k))
                    num[i]++;

        for(i=1;i<=t;i++)
            for(j=0;j<st;j++)
                dp[i][j]=-INF;
        for(i=0;i<=st;i++)
            dp[0][i]=0;
        int stat;
        for(i=1;i<=t;i++)
        {
            for(j=0;j<n;j++)
                scanf("%lf%lf",&x[j],&y[j]);
            determin_place();
            for(j=0;j<st;j++)
                for(k=0;k<tot;k++)
                {
                    stat=pos[k]^(pos[k]&j);
                    if(stat>0)
                        dp[i][j|stat]=max(dp[i][j|stat],dp[i-1][j]+num[stat]*num[stat]);
                }
        }
        int res=0;
        for(i=0;i<st;i++)
            res=max(res,dp[t][i]);
        printf("%d\n",res);
    }
    return 0;
}

 

          

posted @ 2012-10-06 16:14  'wind  阅读(287)  评论(0编辑  收藏  举报