#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int INF=2147483647;
const int mod=300000;
const int M=300005;
struct node{
int to,nxt;
}edge[M];
int head[M],cnt;
int n,m,e1,e2;
int mp[105][15];
int cur,pre; //滚动数组
int state[2][M]; //记录状态,滚动
int ans[2][M],cntt; //记录答案
int tot[2]; //记录状态总数
int bit[10]; //提取状态使用
inline void getbit(){
for(int i=1;i<10;i++)bit[i]=i<<1;
return;
}
inline void add(int u,int v){
cnt++;
edge[cnt].to=v;
edge[cnt].nxt=head[u];
head[u]=cnt;
return;
}
void insert(int now,int num){
int u=now%mod;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(state[cur][v]==now){
ans[cur][v]=max(ans[cur][v],num);
return;
}
}
add(u,++tot[cur]);
state[cur][tot[cur]]=now;
ans[cur][tot[cur]]=num;
return;
}
void plugdp(){
cur=0;
tot[cur]=1;
ans[cur][1]=0;
state[cur][1]=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=tot[cur];j++){
state[cur][j]<<=2;
}
for(int j=1;j<=m;j++){
memset(head,0,sizeof(head));cnt=0;
pre=cur,cur^=1;
tot[cur]=0;
for(int k=1;k<=tot[pre];k++){
int now=state[pre][k];
int num=ans[pre][k]+mp[i][j];
int is_down=(now>>bit[j-1])%4;
int is_right=(now>>bit[j])%4;
if(!is_down&&!is_right){
insert(now,num-mp[i][j]);
if(mp[i][j+1]&&mp[i+1][j])
insert(now+(1<<bit[j-1])+2*(1<<bit[j]),num);
}
else if(!is_down&&is_right){
if(mp[i][j+1])
insert(now,num);
if(mp[i+1][j])
insert(now-is_right*(1<<bit[j])+is_right*(1<<bit[j-1]),num);
}
else if(is_down&&!is_right){
if(mp[i+1][j])
insert(now,num);
if(mp[i][j+1])
insert(now-is_down*(1<<bit[j-1])+is_down*(1<<bit[j]),num);
}
else if(is_down==1&&is_right==1){
int count=1;
for(int l=j+1;l<=m;l++){
if((now>>bit[l])%4==1)count++;
if((now>>bit[l])%4==2)count--;
if(!count){
insert(now-(1<<bit[l])-(1<<bit[j-1])-(1<<bit[j]),num);
break;
}
}
}
else if(is_down==2&&is_right==2){
int count=1;
for(int l=j-2;l>=0;l--){
if((now>>bit[l])%4==1) count--;
if((now>>bit[l])%4==2) count++;
if(!count){
insert(now+(1<<bit[l])-2*(1<<bit[j-1])-2*(1<<bit[j]),num);
break;
}
}
}
else if(is_down==2&is_right==1)
insert(now-2*(1<<bit[j-1])-(1<<bit[j]),num);
else if(is_down==1&&is_right==2){
int count=0;
for(int l=1;l<=m;l++){
if((now>>bit[l])%4)count++;
}
if(count==2)cntt=max(cntt,num);
}
}
}
}
return;
}
int main(){
getbit();
cntt=-INF;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&mp[i][j]);
}
}
plugdp();
printf("%d\n",cntt);
return 0;
}
让人春分日 哈工科教102179.神奇游乐园
最新推荐文章于 2024-08-18 21:07:18 发布