您的位置:首页 > 其它

51nod 1411 矩阵取数问题 V3

2016-09-20 20:00 176 查看
给定一个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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: