题目思路
作为dp白痴 这道简单状压dp都做了快一个半小时
dp太难了
这题反正一开始听lkw和zw讨论说是状压dp 因为他的n很小
晚上我找了下之前做的状压dp题的代码
还是写了很久才成功输出样例
然后一直在t 想了好久怎么优化
最后发现是初始化用memset才t的
有点头疼 不过吃一堑长一智把
改了之后都只有186ms了
这题还有一个挺坑的一点
就是他不止上下左右不能选 左上左下右上右下也不能选
加几个判断的函数就好了
ac代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 1<<16+5;
const int inf = 0x3f3f3f3f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const ll mod = 1000000007;
//998244353
int a[22][22];
int dp[20][maxn],ss[20][maxn];
int st[maxn];
vector<int>vec[maxn];
bool check(int x)
{
return (x&(x<<1));
}
bool judge1(int x,int y)
{
return (st[x]&st[y]);
}
bool judge2(int x,int y)
{
return ((st[x])&(st[y]<<1));
}
bool judge3(int x,int y)
{
return ((st[x])&(st[y]>>1));
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,k=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&a[i][j]);
}
}
for(int i=0;i<(1<<(n));i++)
{
if(!check(i))
{
st[k++]=i;
//printf("%d\n",i);
}
}
//printf("%d\n",k);
for(int i=1;i<=n;i++)
{
for(int j=0;j<k;j++)
{
for(int s=1;s<=n;s++)
{
if((1<<(s-1))&st[j])
{
ss[i][j]+=a[i][s];
}
}
}
}
for(int j=0;j<k;j++)
{
for(int s=0;s<k;s++)
{
if(!judge1(j,s)&&!judge2(j,s)&&!judge3(j,s))
{
vec[j].push_back(s);
vec[s].push_back(j);
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<k;j++)
{
for(int u=0;u<vec[j].size();u++)
{
int tem=vec[j][u];
dp[i][j]=max(dp[i][j],dp[i-1][tem]+ss[i][j]);
}
}
}
int maxx=0;
for(int i=0;i<k;i++)
{
maxx=max(maxx,dp[n][i]);
}
printf("%d\n",maxx);
for(int j=0;j<k;j++) vec[j].clear();
for(int i=1;i<=n;i++)
for(int j=0;j<k;j++)
dp[i][j]=ss[i][j]=0;
}
}