带独立插头的插头dp,注意比环的插头dp的区别主要是在只有一个插头并且是独立插头的时候,有可能可以结束线路,剩下的就是2*2特判变成3*3特判。
然后就是各种打错变量名,还有一个宝贵的经验就是手写二进制分解其实没有太麻烦。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define ll long long
#define inf 1e9
#define eps 1e-8
#define md
#define N 300010
using namespace std;
int n,m;
void outit(int s)
{ int tot=0;
while (s)
{
int t=s&3; if (t==1) tot++; if (t==3) tot--; if (tot<0) tot=-inf;
if (t>>1) printf("1"); else printf("0");
if (t&1) printf("1"); else printf("0");
printf(".");
s>>=2;
}
if (tot<0) while (1);
printf(" ");
}
struct hash
{
int a[N],f[N],s[N];
int sz;
void clear()
{
for (int i=1;i<=sz;i++) a[s[i]]=0;
sz=0;
}
void insert(int S,int F)
{//printf("insert %d: ",S); outit(S); printf("%d\n",F);
if (!a[S]) { a[S]=++sz; f[sz]=F; s[sz]=S;}
else f[a[S]]=max(f[a[S]],F);
}
void ycl()
{
int nn=0;
for (int i=1;i<=sz;i++)
{
a[s[i]]=0;
if (!(s[i]>>(m<<1)))
{
nn++; s[nn]=s[i]<<2; f[nn]=f[i]; a[s[i]<<2]=nn;
}
}
sz=nn;
}
} ha[2];
bool vis_f[N],vis_c[N];
int pr[N][20],C[N];
int a[110][10];
int cur(int s,int x) { return (s>>(x<<1))&3;}
void go(int &s,int x,int d) { s^=(cur(s,x)^d)<<(x<<1); }
void rev(int &s,int x) { s^=(2<<(x<<1));}
int find(int s,int x)
{
if (vis_f[s]) return pr[s][x];
int top=0,q[20];
for (int i=0;i<=m;i++)
{
int now=cur(s,i);
if (now==1) q[++top]=i;
else if (now==3)
{
pr[s][i]=q[top];
pr[s][q[top]]=i;
top--;
}
}
vis_f[s]=1;
return pr[s][x];
}
int count(int s)
{
if (vis_c[s]) return C[s];
for (int i=0;i<=m;i++)
if (cur(s,i)==2) C[s]++;
vis_c[s]=1;
return C[s];
}
int main()
{
int ans=-inf;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=0;j<m;j++)
{
scanf("%d",&a[i][j]);
ans=max(ans,a[i][j]);
}
bool pre=0,now=1; ha[now].clear(); ha[now].insert(0,0);
for (int i=1;i<=n;i++)
for (int j=0;j<m;j++)
{
swap(now,pre); if (j==0) ha[pre].ycl();
ha[now].clear();
for (int k=1;k<=ha[pre].sz;k++)
{
int f=ha[pre].f[k]+a[i][j],S=ha[pre].s[k],s; //printf("ij %d %d %d ",i,j,S); outit(S); printf("\n");
int p=cur(S,j),q=cur(S,j+1);
if (p==0&&q==0)
{
ha[now].insert(S,f-a[i][j]);
s=S; go(s,j,1); go(s,j+1,3); ha[now].insert(s,f);
if (count(S)<2)
{
s=S; go(s,j,2); ha[now].insert(s,f);
s=S; go(s,j+1,2); ha[now].insert(s,f);
}
}
else if (p==0||q==0)
{
int x=p+q; s=S;
go(S,j,0); go(S,j+1,0);
if (x==2&&count(s)==1&&S==0) ans=max(ans,f);
if (x!=2)
{
int y;
if (p==0) y=find(s,j+1); else y=find(s,j);
s=S; go(s,y,2); ha[now].insert(s,f);
}
s=S; go(s,j,x); ha[now].insert(s,f);
s=S; go(s,j+1,x); ha[now].insert(s,f);
}
else
{
s=S; go(S,j,0); go(S,j+1,0);
if (p==1)
{
if (q==1) {
int x=find(s,j+1);
s=S; rev(s,x); ha[now].insert(s,f);
}
else if (q==2) {
int x=find(s,j);
s=S; go(s,x,2); ha[now].insert(s,f);
}
}
else if (p==3)
{
if (q==1) ha[now].insert(S,f);
else if (q==3) {
int x=find(s,j);
s=S; rev(s,x); ha[now].insert(s,f);
}
else {
int x=find(s,j);
s=S; go(s,x,2); ha[now].insert(s,f);
}
}
else
{
if (q==1) {
int x=find(s,j+1);
s=S; go(s,x,2); ha[now].insert(s,f);
}
else if (q==3) {
int x=find(s,j+1);
s=S; go(s,x,2); ha[now].insert(s,f);
}
else { if (S==0) ans=max(ans,f); }
}
}
}
}
printf("%d\n",ans);
return 0;
}