嗯,状态压缩
嗯,其实是一道比较简单的状态压缩,枚举每一种不与上一个状态冲突的情况,然后计算,选择当前状态的最大值
/*状态压缩DP*/
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#define M 1<<21
#define NUM 28657 //总共的状态数
int num;
int state[NUM]; //存储合法状态
int mat[20][20]; //数据
int dp[2][NUM]; //循环数组实现
int n;
void Init()
{
int i;
//得到符合题意的状态数 例如: 1011 & 10110(既1011 <<1 ) =1 可得1011不符合题意
//state[]存储每一种合法状态
for(i=0;i<M;i++){
if(i&(i<<1))continue;
state[num++]=i;
}
}
int get_dp(int i,int x)//状态为x
{
int t=0,sum =0;
while(x){
if(x&1){
sum += mat[i][t];
}
x >>=1;
t++;
}
return sum;
}
void solve()
{
int i,j,k,x;
int max ;
//对第1行进行初始化
for(i=0;state[i]<num;i++){
dp[0][i]=get_dp(0,state[i]);
}
/*for(i=0;state[i]<num;i++){ //额,查询下是否正确,请无视我等小弱吧!
printf("<%d>",state[i]);
printf("<%d>\n",dp[0][i]);
}*/
for(i=1;i<n;i++){ //遍历剩余数组
for(j=0;state[j]<num;j++){ //遍历所有状态
max = -M;
for(k=0;state[k]<num;k++){//遍历上一层的所有状态
if(dp[(i+1)&1][k]!=-1 && (!(state[k]&state[j]))){ //保证上一个状态存在,并且与这次状态不冲突
x = dp[(i+1)&1][k];
if(x>max)max = x;
}
}
dp[i&1][j] = max + get_dp(i,state[j]);
}
}
max = -M;
i--;
for(k=0;state[k]<num;k++){ //遍历最后一行, 找最大值
if(dp[i&1][k] >max)max = dp[i&1][k];
}
printf("%d\n",max);
}
int main(){
int i,j;
Init();
while(~scanf("%d",&n)){
num = 1<<n;
for(i=0;i<n;i++){
for(j=0;j<n;j++)
scanf("%d",&mat[i][j]);
}
solve();
memset(dp,-1,sizeof(dp));
}
return 0;
}