给定一个m行n列的矩阵,你可以从任意位置开始取数,到达任意位置都可以结束,每次可以走到的数是当前这个数上下左右的邻居之一,唯一的限制是每个位置只能经过一次,也就是说你的路径不自交。所经过的数的总作为你的得分,求最大的得分。
Input
第一行两个整数m, n (0 < m, n < 10),表示矩阵的行数和列数。
后面m行,每行n个整数表示矩阵里的数,整数范围[-10000000, +10000000]。
Output
一个整数表示最大得分。
插头dp,状态可以用滚动数组存
#include<cstdio> #include<cstring> int n,m; int v[13][13]; int s0[1048576+7],s1[1048576+11]; bool po[1048576]; const int v0=-2147483647; inline void maxs(int&a,int b){if(a<b)a=b;} inline int _l(int x,int w){ int t=1,a; do{ w-=2; a=x>>w&3; t+=(a>>1)-(a&1); }while(t); return w; } inline int _r(int x,int w){ int t=1,a; do{ w+=2; a=x>>w&3; t-=(a>>1)-(a&1); }while(t); return w; } int main(){ scanf("%d%d",&n,&m); int ans=v0; for(int i=1;i<=n;++i){ for(int j=1;j<=m;++j){ scanf("%d",v[i]+j); if(v[i][j]>ans)ans=v[i][j]; } } if(ans<=0)return printf("%d\n",ans),0; int mx=1<<2*(m+1); for(int i=0;i<mx;++i){ int t=0; for(int j=0;j<=m;++j)t+=((i>>j*2&3)==3); po[i]=(t<=2); } for(int i=0;i<mx;++i)s1[i]=v0; s1[0]=0; for(int i=1;i<=n+1;++i){ for(int j=1;j<=m;++j){ for(int p=0;p<mx;++p){ s0[p]=s1[p]; s1[p]=v0; } for(int p=0;p<mx;++p)if(s0[p]!=v0&&po[p]){ int tt=0; for(int t=0;t<=m;++t)tt+=(p>>t*2&1)+(p>>t*2+1&1); bool is=(tt==2); if(is)maxs(ans,s0[p]); int p1=j*2-2,p2=j*2; int a=p>>p1&3,b=p>>p2&3,c=s0[p]+v[i][j],d1=~(3<<j*2-2),d2=~(3<<j*2); switch(a){ case 0:{ switch(b){ case 0:{ maxs(s1[p],s0[p]); maxs(s1[p|3<<p2],c); maxs(s1[p|3<<p1],c); maxs(s1[p|1<<p1|2<<p2],c); break; } case 1:{ maxs(s1[p],c); maxs(s1[p&d2|1<<p1],c); maxs(s1[p&d1&d2|3<<_r(p,p2)],c); break; } case 2:{ maxs(s1[p],c); maxs(s1[p&d2|2<<p1],c); maxs(s1[p&d1&d2|3<<_l(p,p1)],c); break; } case 3:{ maxs(s1[p],c); maxs(s1[p&d2|3<<p1],c); break; } } break; } case 1:{ switch(b){ case 0:{ maxs(s1[p&d1|1<<p2],c); maxs(s1[p],c); maxs(s1[p&d1|3<<_r(p,p2)],c); break; } case 1:{ maxs(s1[p&d1&d2^3<<_r(p,p2)],c); break; } case 3:{ maxs(s1[p&d1&d2|3<<_r(p,p2)],c); break; } } break; } case 2:{ switch(b){ case 0:{ maxs(s1[p&d1|2<<p2],c); maxs(s1[p],c); maxs(s1[p&d1|3<<_l(p,p1)],c); break; } case 1:{ maxs(s1[p&d1&d2],c); break; } case 2:{ maxs(s1[p&d1&d2^3<<_l(p,p1)],c); break; } case 3:{ maxs(s1[p&d1&d2|3<<_l(p,p1)],c); break; } } break; } case 3:{ switch(b){ case 0:{ maxs(s1[p&d1|3<<p2],c); maxs(s1[p],c); break; } case 1:{ maxs(s1[p&d1&d2|3<<_r(p,p2)],c); break; } case 2:{ maxs(s1[p&d1&d2|3<<_l(p,p1)],c); break; } case 3:{ if(tt==4)maxs(ans,c); break; } } break; } } } if(i==n+1)break; } for(int a=mx-4;a>=0;a-=4){ s1[a+1]=s1[a+2]=s1[a+3]=v0; s1[a]=s1[a>>2]; } } printf("%d",ans); return 0; }