题目链接:hdu 1565
最近真是越来越傻B了,总在输入输出的模块出问题。把二维数组的a【i】【j】变成a【i】了,不提了,真是太傻逼了。
先预处理一下每一行n个数有几种取得情况,(在一行之内两两不相邻),一种情况可以用一个n位的二进制数来表示。
即若第j位上为1,就说明取了第j个数,这样对于每一个i,如果i&i<<1≠0的话,说明i的二进制表示有两个相邻的1,抛弃不要,
否则将i加入状态数组中
然后对于每一个状态j,再预处理出val【i】【j】代表第i行第j种情况所取得的这一行的总值。
dp[i][j]表示第i行第j种情况所取得的最大值。最后dp,枚举第i行的j状态和i-1行的k状态,如果满足s【j】&s【k】==0,则dp【i】【j】=max(dp【i】【j】,dp【i-1】【k】+val【i】【j】);
#include<iostream>
#include<cstdio>
#include<vector>
#include<set>
#include<map>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#define LL long long
#define mod 1000000007
#define inf 0x3f3f3f3f
#define sqr(a) (a)*(a)
#define lan(a,b) memset(a,b,sizeof(a))
using namespace std;
LL dp[30][20010];
LL a[30][30];
LL maxx;
int s[20010];
LL val[30][20010];
int main()
{
int n;
int m=0;;
for(int i=1;i<=(1<<20)-1;i++)
{
if(i&i<<1)
continue;
s[m++]=i;
}
m--;
// printf("%d\n",m);
while(~scanf("%d",&n))
{
maxx=0;
lan(dp,0);
lan(a,0);
lan(val,0);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%lld",&a[i][j]);
for(int i=1;i<=n;i++)
for(int j=0;s[j]<1<<n;j++)
{
int tem=s[j];
// printf("tem=%d\n",tem);
for(int l=1;l<=n;l++)
{
if(tem&1)
{
val[i][j]+=a[i][l];
// printf("ok a%d%d=%lld\n",i,l,a[i][l]);
}
tem>>=1;
}
//printf("val=%d\n",val[i][j]);
}
for(int j=0;s[j]<1<<n;j++)
{
dp[1][j]=val[1][j];
maxx=max(maxx,dp[1][j]);
// printf("%d\n",j);
}
for(int i=2;i<=n;i++)
{
//printf("-%d \n",i);
for(int j=0;s[j]<1<<n;j++)
{
for(int k=0;s[k]<1<<n;k++)
{
if(s[k]&s[j])
continue;
int tem=s[j];
int sum=0;
dp[i][j]=max(dp[i][j],dp[i-1][k]+val[i][j]);
maxx=max(maxx,dp[i][j]);
}
}
}
printf("%lld\n",maxx);
}
return 0;
}