您的位置:首页 > 其它

HYSBZ 1151 动物园zoo - 状压dp

2016-03-20 11:22 399 查看
题目描述

题目大意:

N个动物围成一个环,有K个小朋友,每个小朋友可以看到五个连续的动物,每个小朋友都有自己喜欢或讨厌的动物,当有一个自己讨厌的动物被移走或能看到一个自己喜欢的动物时,这个小朋友就会高兴。求最优的移走动物的方案,使得最多的小朋友高兴。

分析:

dp[i][S]:处理到第i个动物,i~i-3的动物移动与否的状态为S。

dp[i+1][S]=max{dp[i+1][newS],dp[i][S]+Influence} (有移动第i+1个或者不移动两种选择)

Influence:在newS下开心的children数量

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#include<vector>
#define MAXN 10000
#define MAXC 50000
#define MAXS 32
const int S=(1<<4)-1;

int n,c,fear[100],love[100],dp[MAXC+10][MAXS*2+10],happy[MAXC+10][MAXS+10],ans;

void prepare(int st)
{
bool p,q;
for(int s=0;s<=(1<<5)-1;s++){
p=q=false;
for(int j=1;j<=fear[0];j++)
if(!(s&(1<<fear[j]))){
p=true;
break;
}
for(int j=1;j<=love[0];j++)
if(s&(1<<love[j])){
q=true;
break;
}
if(p||q)
happy[st][s]++;
}
} // happy[start_pos][start_pos~5->s]
void read()
{
int pos;
scanf("%d%d",&n,&c);
for(int i=1;i<=c;i++){
scanf("%d%d%d",&pos,&fear[0],&love[0]);
for(int j=1;j<=fear[0];j++){
scanf("%d",&fear[j]);
fear[j]=(fear[j]-pos+n)%n;
}
for(int j=1;j<=love[0];j++){
scanf("%d",&love[j]);
love[j]=(love[j]-pos+n)%n;
}
prepare(pos);
}
}
void DP(int st)
{
memset(dp,-1,sizeof dp);
dp[4][st]=0;
for(int i=4;i<n;i++){
for(int s=0;s<=S;s++){
if(dp[i][s]==-1)
continue;
for(int p=0,k;p<=1;p++){
k=((s&(S^1))>>1)|(p*(1<<3));
dp[i+1][k]=max(dp[i+1][k],dp[i][s]+happy[i-3][s|(p*(1<<4))]);
}
}
}
for(int s=0,k;s<=S;s++){
k=s|((st&1)*(1<<4));
dp
[s]+=happy[n-3][k];
k=((s&(S^1))>>1)|((st&3)*(1<<3));
dp
[s]+=happy[n-2][k];
k=((s&(S^3))>>2)|((st&7)*(1<<2));
dp
[s]+=happy[n-1][k];
k=((s&(1<<3))>>3)|(st<<1);
dp
[s]+=happy
[k];
ans=max(ans,dp
[s]);
}
}
void workout()
{
for(int s=0;s<=S;s++)
DP(s);
printf("%d\n",ans);
}
int main()
{
read();
workout();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: