也是比较经典的轮廓线动态规划问题,每一个格子可以放或者不放,0和1表示,那么就是判断上一个状态的左边和上边是否已经选了,注意一下列首的时候不用判断前一个是否放了,有一个地方要注意一下,因为对于每一个状态 枚举的时候可能枚举到不符合要求的状态,如果判断单独来判断该状态是否符合规范 比较麻烦 因为首列的两个1可以并列,所以比较麻烦,这里的处理办法就是初始化为-1,更新了的状态肯定是符合要求的那么对于上一个状态如果是-1 那么就不要更新
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
#define LL long long
LL dp[2][1<<20];
int main()
{
int n;
while(scanf("%d",&n) != EOF)
{
LL mp[25][25];
memset(dp,-1,sizeof(dp));
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n;j++)
{
scanf("%lld",&mp[i][j]);
}
}
dp[0][0] = 0;
int cur = 0;
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n;j++)
{
for(int k = 0;k<(1<<n);k++)
{
if(dp[cur][k]<0)continue;
// 放
if((j==0 || (k&1)==0) && (k&(1<<(n-1)))==0)
{
dp[1-cur][(k<<1)|1] = max(dp[1-cur][(k<<1)|1],dp[cur][k]+mp[i][j]);
}
// 不放
dp[1-cur][(k<<1) & (1<<n)-1] = max(dp[1-cur][(k<<1) & (1<<n)-1],dp[cur][k]);
}
memset(dp[cur],-1,sizeof(dp[cur]));
cur = cur^1;
}
}
LL ans = 0;
for(int i = 0;i<(1<<n);i++)
{
ans = max(ans,dp[cur][i]);
}
printf("%lld\n",ans);
}
return 0;
}