首页 > 代码库 > hdu 2167状态压缩dp

hdu 2167状态压缩dp

和杭电上的取石子这道题差不多就是多了个斜着也不行    其次就是输入格式了

先预处理下   把所有满足一行的所有状态列出来   并把相应的和求出来

然后按照dp相应的思路求  

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;


int num[20][20];
int mark[1<<16];
int sum[20][1<<16],have[100000],cont;
int n;
int deal()
{
int i;
cont=0;
int t=1<<n;
memset(sum,0,sizeof(sum));
//printf("%d\n",t);
for(i=0;i<t;i++)
{
if(i&(i<<1)) continue;
have[++cont]=i;
if(i==0) continue;
int a=i,b=n;
while(a/2)
{
if(a%2)
{
for(int k=1;k<=n;k++)
{
sum[k][cont]+=num[k][b];
}
}
a/=2;
b--;
}
for(int k=1;k<=n;k++)
sum[k][cont]+=num[k][b];
}
return 0;
}
int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
char str[500];
int i,j;
while(gets(str))
{
int len=strlen(str);
int t=0;
for(i=0,j=0;i<=len;i++)
{
if(str[i]==‘ ‘||i==len)
{
t++;
num[1][++j]=str[i-1]-‘0‘+(str[i-2]-‘0‘)*10;
}
}
for(i=2;i<=t;i++)
for(j=1;j<=t;j++)
scanf("%d",&num[i][j]);
n=t;
deal();
int dp[20][1<<n];
memset(dp,0,sizeof(dp));

for(i=0;i<=cont;i++)
{
dp[1][i]+=sum[1][i];
}
for(i=2;i<=n;i++)
{
for(j=1;j<=cont;j++)
{
for(int k=1;k<=cont;k++)
{
if(have[j]&have[k]) continue;
if(have[j]&(have[k]<<1)) continue;
if(have[j]&(have[k]>>1)) continue;
dp[i][j]=max(dp[i][j],dp[i-1][k]+sum[i][j]);
}
}
}
int Max=0;
for(i=1;i<=n;i++)
for(j=1;j<=cont;j++)
if(dp[i][j]>Max) Max=dp[i][j];
printf("%d\n",Max);
getchar();
getchar();
}
return 0;
}

hdu 2167状态压缩dp