标签:des style blog color io os java ar strong
3 75 15 21 75 15 28 34 70 5
188
思路:枚举每个状态,得到最优解。枚举上下两个状态时,应判断它们之间是否矛盾,用一个二进制数可以记录每一行的一种取法,即相邻的两位的数字不能都为1,间隔取数。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 21
#define M 30000
int state[M];
int a[N][N];
int dp[N][M];
int n,lim;
void inti() //得到一行能取的数的所有集合
{ //每个数组元素代表一种取法
int i,k;
for(i=k=0;i<=(1<<20);i++)
{
if(i&(i<<1)) //每个数字左移一位,若与自身相与为真
continue; //这个数字肯定有相邻两位都为1.
state[k++]=i; //i=1101 ,左移一位后为ii=11010 ,
}
}
int getsum(int i,int x) //得到该种取法的数组和
{
int t,sum;
t=sum=0;
while(x)
{
if(x&1) //相与为真则这个数字能取
sum+=a[i][t];
x>>=1;
t++;
}
return sum;
}
void solve()
{
int i,j,k;
lim=1<<n;
for(i=0;state[i]<lim;i++)
{
dp[0][i]=getsum(0,state[i]);
}
for(i=1;i<n;i++) //遍历剩下的数组
{
for(j=0;state[j]<lim;j++) //对于每一行可取的状态
{
int tmp=0;
for(k=0;state[k]<lim;k++) //找到上一行能取得最大值
{
if(!(state[j]&state[k])) //相邻两行不矛盾
tmp=max(tmp,dp[i-1][k]);
}
dp[i][j]=tmp+getsum(i,state[j]);
}
}
int ans=0;
for(i=0;state[i]<lim;i++)
ans=max(ans,dp[n-1][i]);
printf("%d\n",ans);
}
int main()
{
int i,j;
inti();
while(scanf("%d",&n)!=-1)
{
if(n==0) //特判
{
printf("0\n");
continue;
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&a[i][j]);
}
}
solve();
}
return 0;
}
标签:des style blog color io os java ar strong
原文地址:http://blog.csdn.net/u011721440/article/details/39547081