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; }