/* 状态转移方程:dp[i][j]=Max(dp[i][j],dp[i-1][k]+sum[i][j]); */ #include<stdio.h> #include<string.h> #define N 16 int ma[N][N]; int num[N]; char s[150]; int lower[15];//储存二级制 int dp[N][1<<N];//储存最优状态 int now[1<<N],cu;//储存合法的状态 int sum[N][1<<N];//储存第i行第j个状态的总的权值和 int Max(int a,int b) { return a>b?a:b; } int main() { int n,i,j,k,maxx; lower[0]=1; for(i=1; i<=15; i++) lower[i]=lower[i-1]*2; while(gets(s)) { k=0; j=0; n=0; for(i=0; s[i]; i++) { if(j&&s[i]==' ') { ma[1][++n]=k; j=0; k=0; } if(s[i]>='0'&&s[i]<='9') { k=k*10+s[i]-'0'; j=1; } } if(j) ma[1][++n]=k; for(i=2; i<=n; i++) for(j=1; j<=n; j++) scanf("%d",&ma[i][j]); cu=0; for(i=0; i<(1<<n); i++)//储存合法的状态 { if(i<<1&i)continue; now[++cu]=i; } memset(sum,0,sizeof(sum)); memset(dp,0,sizeof(dp)); for(i=1; i<=n; i++) for(j=1; j<=cu; j++) for(k=0; k<n; k++)//因为在二进制中1代表的就是lower[0],如果k从1开始的话,lower[1]=2,就缺少了1的情况 if(lower[k]&now[j])sum[i][j]+=ma[i][k+1];//lower[k]才是有效地 for(i=1; i<=cu; i++)//初始化第一行 dp[1][i]=sum[1][i]; for(i=2; i<=n; i++) for(j=1; j<=cu; j++) for(k=1; k<=cu; k++) { if(now[j]&now[k])continue; if(now[j]&(now[k]<<1))continue;//如果和对角线和上面都没有相邻就符合 if(now[j]&(now[k]>>1))continue; dp[i][j]=Max(dp[i][j],dp[i-1][k]+sum[i][j]); } maxx=-1; for(i=1; i<=cu; i++)//求出所有状态的最大值 if(maxx<dp[n][i]) maxx=dp[n][i]; printf("%d ",maxx); gets(s); gets(s); } return 0; }