您的位置:首页 > 其它

HDU 1565——方格取数(1)

2013-05-08 23:29 351 查看
状态压缩DP

每行最多有20个格子,每个格子取用1表示,不取用0表示。

3

75 15 21

75 15 28

34 70 5

188
这样每一行的状态都能用一个数字来,例如75 15 21,如果取75和21,则用101也就是5.

#include<iostream>
#include<cstring>
using namespace std;
int map[24][24];
int num[24];
int str[17720],N;
int dp[2][17720];

bool judge(int x)
{
int end=0;
while(x)
{
if(end==1&&x%2)
return 0;
end=x%2;
x/=2;
}
return 1;
}

void init()
{
int i;
num[1]=1;
for(i=2;i<=20;i++)
num[i]=num[i-1]<<1;
N=1;
for(i=1;i<=num[20];i++)
if(judge(i))
str[N++]=i;
// cout<<N; //N=17711 在这里可以计算出取得格子不相连的状态数

}

int Max(int a,int b)
{
return a>b?a:b;
}

int main()
{
int n;
int max;
int i,j;
init();
while(cin>>n)
{
int i,j,k;
max=0;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
cin>>map[i][j];
memset(dp,0,sizeof(dp));

for(i=1;i<=N;i++)//考虑第一层的状态
{
if(str[i]>num[n+1])//状态
break;
for(j=1;j<=n;j++)//计算当前状态能获得的权值
{
if(str[i]&num[j])
dp[0][i]+=map[1][j];
}
}
for(k=2;k<=n;k++)
{
for(i=1;i<=N;i++)
{
int temp=0;
if(str[i]>num[n+1])
break;
for(j=1;j<=n;j++)
{
if(str[i]&num[j])
temp+=map[k][j];
}
for(j=1;j<=N;j++)
{
if(!(str[i]&str[j]))
dp[1][i]=Max(dp[1][i],dp[0][j]+temp);
}
}
for(i=1;i<=N;i++)
{
if(str[i]>num[n+1])
break;
dp[0][i]=dp[1][i];
dp[1][i]=0;
}
}
max=0;
for(i=1;i<=N;i++)
{
if(str[i]>num[n+1])
break;
max=Max(dp[0][i],max);
}
cout<<max<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: