还是一道插头DP
不过我的代码跑的好慢啊啊,要卡卡常才能过
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
const int N=20010,inf=1<<30;
int n,m;
int f[10][10][4][N];
int pw[15],a[15][15];
int d[N][10];
inline void fix(int &x,int y){
if(x>y) x=y;
}
inline int cg(int s,int p,int t){
return ((s/pw[p])*3+t)*pw[p-1]+s%pw[p-1];
}
int main(){
pw[0]=1;
for(int i=1;i<=9;i++) pw[i]=pw[i-1]*3;
for(int i=0;i<pw[9];i++)
for(int j=0;j<=9;j++)
d[i][j]=(i/pw[j])%3;
while(1){
scanf("%d%d",&n,&m);
if(!n || !m) break;
memset(f,0x7f,sizeof(f));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
f[0][m][0][0]=0;
for(int i=1;i<=n;i++){
for(int j=0;j<pw[m];j++)
f[i][0][0][j]=f[i-1][m][0][j];
for(int j=0;j<m;j++)
for(int S=0;S<pw[m];S++)
for(int t=0;t<3;t++){
int s=d[S][j],cur=f[i][j][t][S];
int (*nxt)[N]=f[i][j+1];
if(cur>=inf) continue;
if(a[i][j+1]==2){
if((s && t) || s==2 || t==2) continue;
if(!s && !t)
fix(nxt[1][cg(S,j+1,0)],cur+1),fix(nxt[0][cg(S,j+1,1)],cur+1);
else
fix(nxt[0][cg(S,j+1,0)],cur);
}
else if(a[i][j+1]==3){
if((s && t) || s==1 || t==1) continue;
if(!s && !t)
fix(nxt[2][cg(S,j+1,0)],cur+1),fix(nxt[0][cg(S,j+1,2)],cur+1);
else
fix(nxt[0][cg(S,j+1,0)],cur);
}
else if(a[i][j+1]==0){
if(s && t && s!=t) continue;
if(s && t)
fix(nxt[0][cg(S,j+1,0)],cur);
else if((s || t) && (!s || !t))
fix(nxt[0][cg(S,j+1,s|t)],cur+1),fix(nxt[s|t][cg(S,j+1,0)],cur+1);
else if(!s && !t)
fix(nxt[0][cg(S,j+1,0)],cur),fix(nxt[1][cg(S,j+1,1)],cur+2),fix(nxt[2][cg(S,j+1,2)],cur+2);
}
else{
if(s || t) continue;
fix(nxt[0][cg(S,j+1,0)],cur);
}
}
}
printf("%d\n",f[n][m][0][0]>=inf?0:f[n][m][0][0]);
}
return 0;
}