插头DP专题
fzu 1977 格子分三种:不能走,可走可不走,一定要走。求单回路条数。
如果左上插头都为0 并且此格子可以不走 直接将状态加入到hash表中。记录最后一个必须走的格子 此后如果有回路形成 加入到结果。有回路形成 left=1 up=2 并且其它位置要全为0 为此WA了一晚上。。
另外 若plugDP最后return dp[0] 测试数据又无解 应写成
if(src->sz==0) return 0;
return src->dp[0]-2;
int M[15]; const int HSize = 12397; int n , m , nn , mm ; int maze[15][15]; int vis[15][15]; inline int CP(int p, int i) { return p & ( ~( 3 << M[i] ) ); }//第i位置零 inline int CP(int p, int i, int j) { return p & ( ~( 3 << M[i] ) ) & ( ~( 3 << M[j] ) ); }//i j位置零 inline int CP(int p, int i, int j, int k) { return p & ( ~( 3 << M[i] ) ) & ( ~( 3 << M[j] ) ) & ( ~( 3 << M[k] ) ); }//ijk置零 inline int getP(int p, int i) { return 3 & ( p >> M[i] ); }//取第i位 inline int setP(int i, int k) { return k << M[i]; }//第i位置为k inline int getLP(int p, int j) {//找对应的左括号 for ( int it = j - 1 , cnt = 1 ; ; it -- ) { int Pi = getP(p, it); if ( Pi == 1 ) cnt --; else if ( Pi == 2 ) cnt ++; if ( cnt == 0 ) return it; } } inline int getRP(int p, int j) {//找对应的右括号 for ( int it = j + 1 , cnt = 1 ; ; it ++ ) { int Pi = getP(p, it); if ( Pi == 2 ) cnt --; else if ( Pi == 1 ) cnt ++; if ( cnt == 0 ) return it; } } struct HashMap { int Chart[HSize] , next[HSize] , sz; int MSK[HSize] ; long long dp[HSize] ; void clear() { sz = 0; memset(Chart, -1, sizeof( Chart )); } inline void push(int msk, long long val) { int x = msk % HSize; for ( int it = Chart[x] ; it != -1 ; it = next[it] ) { if ( MSK[it] == msk ) { dp[it]+=val; return; } } MSK[sz] = msk; dp[sz] = val; next[sz] = Chart[x]; Chart[x] = sz ++; } } HM[2] , *src , *des; long long PlugDP() { src = HM; des = src + 1; src->clear(); src->push(0, 1); long long ans=0; for ( int i = 0 ; i < n ; i ++ ) { for ( int k = 0 ; k < src->sz ; k ++ ) src->MSK[k] <<= 2; for ( int j = 0 ; j < m ; j ++ ) { if ( !vis[i][j] ) continue; des->clear(); for ( int k = 0 ; k < src->sz ; k ++ ) { int msk = src->MSK[k]; long long val = src->dp[k] ; int left = getP(msk, j); int up = getP(msk, j + 1); if ( !left && !up ) { if ( vis[i][j] == 1 ) des->push(msk , val); if ( vis[i][j + 1] && vis[i + 1][j] ) des->push(msk | setP(j, 1) | setP(j + 1, 2), val); } else if ( !left || !up ) { int w = left + up; int temp = CP(msk, j, j + 1); if ( vis[i + 1][j] ) des->push(temp | setP(j, w), val); if ( vis[i][j + 1] ) des->push(temp | setP(j + 1, w), val); } else if ( left == up ) { int it = ( left == 1 ) ? getRP(msk, j+1) : getLP(msk, j); des->push(CP(msk, j, j + 1, it) | setP(it, left), val); } else if ( left == 2 && up == 1 ) des->push(CP(msk, j, j + 1), val); else if ( (i > nn || (i==nn&&j>=mm)) && left == 1 && up == 2 ) //des->push(CP(msk, j, j + 1), val); if(CP(msk,j,j+1)==0) ans+=val; } swap(src, des); } } return //src->dp[0]; ans; } int main() { for ( int i = 0 ; i < 15 ; i ++ ) M[i] = ( i << 1 ); int T; cin>>T; for ( int Case=1;Case<=T;Case++ ) { cin>>n>>m; string s="123456789012345"; //memset(maze,0,sizeof(maze)); for ( int i = 0 ; i < n ; i ++ ){ cin>>s; for ( int j = 0 ; j < m ; j ++ ){ if(s[j]=='*') maze[i][j]=1; else if(s[j]=='O') maze[i][j]=2; else maze[i][j]=0; } } if ( n < m ) { for ( int i = 0 ; i < n ; i ++ ) for ( int j = i + 1 ; j < m ; j ++ ) swap(maze[i][j], maze[j][i]); swap(n, m); } nn=n-1; mm=m-1; memset(vis, false, sizeof( vis )); for ( int i = 0 ; i < n ; i ++ ) for ( int j = 0 ; j < m ; j ++ ){ if(maze[i][j]) vis[i][j] = maze[i][j] ; if(maze[i][j]==2) nn=i,mm=j; } printf("Case %d: %I64d\n",Case,PlugDP()); //cout<<"Case "<<Case<<": "<<PlugDP()<<endl; } return 0; }
hdu 1693 多回路
const int HSize = 199997; int n , m; int maze[13][13]; bool vis[13][13]; inline int CP(int p, int i) { return p & ( ~( 1 << i ) ); }//第i位置零 inline int CP(int p, int i, int j) { return p & ( ~( 1 << i ) ) & ( ~( 1 << j ) ); }//i j位置零 inline int CP(int p, int i, int j, int k) { return p & ( ~( 1 << i ) ) & ( ~( 1 << j ) ) & ( ~( 1 << k ) ); }//ijk置零 inline int getP(int p, int i) { return 1 & ( p >> i ); }//取第i位 inline int setP(int i, int k) { return k << i; }//第i位置为k struct HashMap { int Chart[HSize] , next[HSize] , sz; int MSK[HSize] ; unsigned long long dp[HSize]; void clear() { sz = 0; memset(Chart, -1, sizeof( Chart )); } inline void push(int msk, unsigned long long val) { int x = msk % HSize; for ( int it = Chart[x] ; it != -1 ; it = next[it] ) { if ( MSK[it] == msk ) { dp[it]+=val; return; } } MSK[sz] = msk; dp[sz] = val; next[sz] = Chart[x]; Chart[x] = sz ++; } } HM[2] , *src , *des; long long PlugDP() { src = HM; des = src + 1; src->clear(); src->push(0, 1); for ( int i = 0 ; i < n ; i ++ ) { for ( int k = 0 ; k < src->sz ; k ++ ) src->MSK[k] <<= 1; for ( int j = 0 ; j < m ; j ++ ) { if ( !vis[i][j] ) continue; des->clear(); for ( int k = 0 ; k < src->sz ; k ++ ) { int msk = src->MSK[k]; unsigned long long val = src->dp[k] ; int left = getP(msk, j); int up = getP(msk, j + 1); if ( !left && !up ) { if ( vis[i][j + 1] && vis[i + 1][j] ) des->push(msk | setP(j, 1) | setP(j + 1, 1), val); } else if ( !left || !up ) { int w = left + up; int temp = CP(msk, j, j + 1); if ( vis[i + 1][j] ) des->push(temp | setP(j, w), val); if ( vis[i][j + 1] ) des->push(temp | setP(j + 1, w), val); } else { int temp = CP(msk, j, j + 1); des->push(temp , val); } } swap(src, des); } } return src->dp[0]; } int main() { int T; scanf("%d", &T); for(int t=1;t<=T;t++) { scanf("%d%d", &n, &m);//n行m列 for ( int i = 0 ; i < n ; i ++ ) for ( int j = 0 ; j < m ; j ++ ) scanf("%d", &maze[i][j]); if ( n < m ) { for ( int i = 0 ; i < n ; i ++ ) for ( int j = i + 1 ; j < m ; j ++ ) swap(maze[i][j], maze[j][i]); swap(n, m); } memset(vis, false, sizeof( vis )); for ( int i = 0 ; i < n ; i ++ ) for ( int j = 0 ; j < m ; j ++ ) if ( maze[i][j] ) vis[i][j] = true; cout<<"Case "<<t<<": There are "<<PlugDP()<<" ways to eat the trees."<<endl; } return 0; }
poj 1739 单路径 从左下角走到右下角
分析:在最下面加一行 左边和右边两个格子为无障碍 其它为障碍 最后统计状态为100……002即可
int M[15]; const int HSize = 407; int n , m; bool vis[15][15]; inline int CP(int p, int i) { return p & ( ~( 3 << M[i] ) ); }//第i位置零 inline int CP(int p, int i, int j) { return p & ( ~( 3 << M[i] ) ) & ( ~( 3 << M[j] ) ); }//i j位置零 inline int CP(int p, int i, int j, int k) { return p & ( ~( 3 << M[i] ) ) & ( ~( 3 << M[j] ) ) & ( ~( 3 << M[k] ) ); }//ijk置零 inline int getP(int p, int i) { return 3 & ( p >> M[i] ); }//取第i位 inline int setP(int i, int k) { return k << M[i]; }//第i位置为k inline int getLP(int p, int j) {//找对应的左括号 for ( int it = j - 1 , cnt = 1 ; ; it -- ) { int Pi = getP(p, it); if ( Pi == 1 ) cnt --; else if ( Pi == 2 ) cnt ++; if ( cnt == 0 ) return it; } } inline int getRP(int p, int j) {//找对应的右括号 for ( int it = j + 1 , cnt = 1 ; ; it ++ ) { int Pi = getP(p, it); if ( Pi == 2 ) cnt --; else if ( Pi == 1 ) cnt ++; if ( cnt == 0 ) return it; } } struct HashMap { int Chart[HSize] , next[HSize] , sz; int MSK[HSize] ; long long dp[HSize] ; void clear() { sz = 0; memset(Chart, -1, sizeof( Chart )); } inline void push(int msk, long long val) { int x = msk % HSize; for ( int it = Chart[x] ; it != -1 ; it = next[it] ) { if ( MSK[it] == msk ) { dp[it]+=val; return; } } MSK[sz] = msk; dp[sz] = val; next[sz] = Chart[x]; Chart[x] = sz ++; } } HM[2] , *src , *des; long long PlugDP() { src = HM; des = src + 1; src->clear(); src->push(0, 1); for ( int i = 0 ; i < n ; i ++ ) { for ( int k = 0 ; k < src->sz ; k ++ ) src->MSK[k] <<= 2; for ( int j = 0 ; j < m ; j ++ ) { if ( !vis[i][j] ) continue; des->clear(); for ( int k = 0 ; k < src->sz ; k ++ ) { int msk = src->MSK[k]; long long val = src->dp[k] ; int left = getP(msk, j); int up = getP(msk, j + 1); if ( left==0 && up==0 ) { if ( vis[i][j + 1] && vis[i + 1][j] ) des->push(msk | setP(j, 1) | setP(j + 1, 2), val); } else if ( left==0 || up==0 ) { int w = left + up; int temp = CP(msk, j, j + 1); if ( vis[i + 1][j] ) des->push(temp | setP(j, w), val); if ( vis[i][j + 1] ) des->push(temp | setP(j + 1, w), val); } else if ( left == up ) { int it = ( left == 1 ) ? getRP(msk, j+1) : getLP(msk, j); des->push(CP(msk, j, j + 1, it) | setP(it, left), val); } else if ( left == 2 && up == 1 ) des->push(CP(msk, j, j + 1), val); } swap(src, des); } } long long sta=(2<<(2*m-2))+1; for ( int k = 0 ; k < src->sz ; k ++ ) { if(src->MSK[k]==sta) return src->dp[k]; } return 0; } int main() { for ( int i = 0 ; i < 15 ; i ++ ) M[i] = ( i << 1 ); /*while ( scanf("%d%d",&n,&m),n ) { memset(vis, false, sizeof( vis )); char ch; for ( int i = 0 ; i < n ; i ++ ){ scanf("%c",&ch); for ( int j = 0 ; j < m ; j ++ ){ scanf("%c", &ch); if( ch == '.'){ vis[i][j]=1; } } }*/ while ( cin>>n>>m,n ) { memset(vis, false, sizeof( vis )); char ch; for ( int i = 0 ; i < n ; i ++ ){ for ( int j = 0 ; j < m ; j ++ ){ cin>>ch; if( ch == '.'){ vis[i][j]=1; } } } vis[n][0]=vis[n][m-1]=1; //printf("%I64d\n", PlugDP()); cout<<PlugDP()<<endl; } return 0; }
poj 3133 有两个格子为2 两个格子为3 要求2到2连起来 3到3连起来 并使连线最短
插头设置为0是没插头,1是连接关键点2的线,2是连接关键点3的线。
对于0的格子:00 -> 00,11,22;01/10 -> 01/10;02/20 -> 02/20;11/22 -> 00。
对于1的格子:00 -> 00。
对于2的格子:01/10 -> 00,00 -> 01/10。
对于3的格子:02/20 -> 00,00 -> 02/20。
int M[15]; const int HSize = 11137; int n , m ; int maze[15][15]; int vis[15][15]; inline int CP(int p, int i) { return p & ( ~( 3 << M[i] ) ); }//第i位置零 inline int CP(int p, int i, int j) { return p & ( ~( 3 << M[i] ) ) & ( ~( 3 << M[j] ) ); }//i j位置零 inline int CP(int p, int i, int j, int k) { return p & ( ~( 3 << M[i] ) ) & ( ~( 3 << M[j] ) ) & ( ~( 3 << M[k] ) ); }//ijk置零 inline int getP(int p, int i) { return 3 & ( p >> M[i] ); }//取第i位 inline int setP(int i, int k) { return k << M[i]; }//第i位置为k inline int getLP(int p, int j) {//找对应的左括号 for ( int it = j - 1 , cnt = 1 ; ; it -- ) { int Pi = getP(p, it); if ( Pi == 1 ) cnt --; else if ( Pi == 2 ) cnt ++; if ( cnt == 0 ) return it; } } inline int getRP(int p, int j) {//找对应的右括号 for ( int it = j + 1 , cnt = 1 ; ; it ++ ) { int Pi = getP(p, it); if ( Pi == 2 ) cnt --; else if ( Pi == 1 ) cnt ++; if ( cnt == 0 ) return it; } } struct HashMap { int Chart[HSize] , next[HSize] , sz; int MSK[HSize] ; long long dp[HSize] ; void clear() { sz = 0; memset(Chart, -1, sizeof( Chart )); } inline void push(int msk, long long val) { int x = msk % HSize; for ( int it = Chart[x] ; it != -1 ; it = next[it] ) { if ( MSK[it] == msk ) { dp[it] = dp[it] < val ? dp[it] : val; return; } } MSK[sz] = msk; dp[sz] = val; next[sz] = Chart[x]; Chart[x] = sz ++; } } HM[2] , *src , *des; long long PlugDP() { src = HM; des = src + 1; src->clear(); src->push(0, 0); //long long ans=0; for ( int i = 0 ; i < n ; i ++ ) { for ( int k = 0 ; k < src->sz ; k ++ ) src->MSK[k] <<= 2; for ( int j = 0 ; j < m ; j ++ ) { if ( !vis[i][j] ) continue; des->clear(); if(vis[i][j]==2) for ( int k = 0 ; k < src->sz ; k ++ ) { int msk = src->MSK[k]; long long val = src->dp[k] + 1; int left = getP(msk, j); int up = getP(msk, j + 1); if(up+left==1) des->push(CP(msk,j,j+1),val); else if(!left&&!up){ int temp=CP(msk,j,j+1); if(vis[i+1][j])des->push(temp|setP(j,1),val); if(vis[i][j+1])des->push(temp|setP(j+1,1),val); } } else if(vis[i][j]==3) for ( int k = 0 ; k < src->sz ; k ++ ) { int msk = src->MSK[k]; long long val = src->dp[k] + 1; int left = getP(msk, j); int up = getP(msk, j + 1); if((left==2&&up==0)||(left==0&&up==2)) des->push(CP(msk,j,j+1),val); else if(!left&&!up){ int temp=CP(msk,j,j+1); if(vis[i+1][j])des->push(temp|setP(j,2),val); if(vis[i][j+1])des->push(temp|setP(j+1,2),val); } } else for ( int k = 0 ; k < src->sz ; k ++ ) { int msk = src->MSK[k]; long long val = src->dp[k] + 1; int left = getP(msk, j); int up = getP(msk, j + 1); if ( !left && !up ) { des->push(msk , val - 1); if ( vis[i][j + 1] && vis[i + 1][j] ) { des->push(msk | setP(j, 1) | setP(j + 1, 1), val); des->push(msk | setP(j, 2) | setP(j + 1, 2), val); } } else if ( !left || !up ) { int w = left + up; int temp = CP(msk, j, j + 1); if ( vis[i + 1][j] ) des->push(temp | setP(j, w), val); if ( vis[i][j + 1] ) des->push(temp | setP(j + 1, w), val); } else if ( left == up ) { des->push(CP(msk, j, j + 1), val); } } swap(src, des); } } if(src->sz==0) return 0; //无解 return src->dp[0]-2; //ans; } int main() { for ( int i = 0 ; i < 15 ; i ++ ) M[i] = ( i << 1 ); while ( cin>>n>>m && n ) { for ( int i = 0 ; i < n ; i ++ ) for ( int j = 0 ; j < m ; j ++ ) cin>>maze[i][j]; if ( n < m ) { for ( int i = 0 ; i < n ; i ++ ) for ( int j = i + 1 ; j < m ; j ++ ) swap(maze[i][j], maze[j][i]); swap(n, m); } memset(vis, 0, sizeof( vis )); for ( int i = 0 ; i < n ; i ++ ) for ( int j = 0 ; j < m ; j ++ ) if ( maze[i][j] == 0 ) vis[i][j] = 1; else if( maze[i][j] == 2) vis[i][j]=2; else if( maze[i][j] == 3) vis[i][j]=3; printf("%I64d\n",PlugDP()); //cout<<PlugDP()<<endl; } return 0; }
Timus 1519 多回路
int Pos[15],cp[15],sp[4][15]; const int HSize = 32117; int n , m , nn , mm ; int maze[15][15]; int vis[15][15]; // state & cp[i] 将第i位置为0 // state & cp[i] | sp[k][i] 将第i位置为k void init(){ for ( int i = 0 ; i < 15 ; i ++ ){ Pos[i] = ( i << 1 ); cp[i] = ~( 3 << Pos[i]); } for ( int i = 0 ; i < 4 ; i ++ ) for ( int j = 0 ; j < 15 ; j ++ ) sp[i][j] = i << Pos[j]; } void readData(){ char ch; for ( int i = 0 ; i < n ; i ++ ){ for ( int j = 0 ; j < m ; j ++ ){ cin>>ch; maze[i][j]=ch=='.'; } } if ( n < m ) { for ( int i = 0 ; i < n ; i ++ ) for ( int j = i + 1 ; j < m ; j ++ ) swap(maze[i][j], maze[j][i]); swap(n, m); } memset(vis, 0, sizeof( vis )); for ( int i = 0 ; i < n ; i ++ ) for ( int j = 0 ; j < m ; j ++ ) if ( maze[i][j] ) vis[i][j] = 1,nn=i,mm=j; } inline int getP(int p, int i) { return 3 & ( p >> Pos[i] ); }//取第i位 inline int getLP(int p, int j) {//找对应的左括号 for ( int it = j - 1 , cnt = 1 ; ; it -- ) { int Pi = getP(p, it); if ( Pi == 1 ) cnt --; else if ( Pi == 2 ) cnt ++; if ( cnt == 0 ) return it; } } inline int getRP(int p, int j) {//找对应的右括号 for ( int it = j + 1 , cnt = 1 ; ; it ++ ) { int Pi = getP(p, it); if ( Pi == 2 ) cnt --; else if ( Pi == 1 ) cnt ++; if ( cnt == 0 ) return it; } } struct HashMap { int Chart[HSize] , pre[HSize] , sz; int State[HSize] ; long long dp[HSize] ; void clear() { sz = 0; memset(Chart, -1, sizeof( Chart )); } inline void push(int sta, long long val) { int x = sta % HSize; for ( int it = Chart[x] ; it != -1 ; it = pre[it] ) { if ( State[it] == sta ) { dp[it]+=val; return; } } State[sz] = sta; dp[sz] = val; pre[sz] = Chart[x]; Chart[x] = sz ++; } } HM[2] , *src , *des; long long PlugDP() { src = HM; des = src + 1; src->clear(); src->push(0, 1); long long ans=0; for ( int i = 0 ; i < n ; i ++ ) { for ( int k = 0 ; k < src->sz ; k ++ ) src->State[k] <<= 2; for ( int j = 0 ; j < m ; j ++ ) { if ( !vis[i][j] ) continue; des->clear(); for ( int k = 0 ; k < src->sz ; k ++ ) { int sta = src->State[k]; long long val = src->dp[k] ; int left = getP(sta, j); int up = getP(sta, j + 1); if ( !left && !up ) { if ( vis[i][j + 1] && vis[i + 1][j] ) des->push(sta | sp[1][j] | sp[2][j+1], val); } else if ( !left || !up ) { int w = left + up; int temp = sta & cp[j] & cp[j+1]; if ( vis[i + 1][j] ) des->push(temp | sp[w][j], val); if ( vis[i][j + 1] ) des->push(temp | sp[w][j+1], val); } else if ( left == up ) { int it = ( left == 1 ) ? getRP(sta, j+1) : getLP(sta, j); des->push(sta & cp[j] & cp[j+1] & cp[it] | sp[left][it], val); } else if ( left == 2 && up == 1 ) des->push(sta & cp[j] & cp[j+1], val); else if ( i == nn && j == mm && left == 1 && up == 2 ) //des->push(CP(sta, j, j + 1), val); ans+=val; } swap(src, des); } } return //src->dp[0]; ans; } int main() { init(); while (cin>>n>>m) { readData(); printf("%I64d\n",PlugDP()); } return 0; }
zju 3213 花园被分成m*m的方块 有的方块是障碍,每个方块有权值 障碍的权值为0,非障碍方块只能走一次 问怎么走经过的权值最大
简单路径 不过不是求路线条数 而是求权值 不一定要走完所有非障碍方块
int M[10]; const int HSize = 30007; int n , m; int maze[7][7]; bool vis[8][8]; inline int CP(int p, int i) { return p & ( ~( 3 << M[i] ) ); }//第i位置零 inline int CP(int p, int i, int j) { return p & ( ~( 3 << M[i] ) ) & ( ~( 3 << M[j] ) ); }//i j位置零 inline int CP(int p, int i, int j, int k) { return p & ( ~( 3 << M[i] ) ) & ( ~( 3 << M[j] ) ) & ( ~( 3 << M[k] ) ); }//ijk置零 inline int getP(int p, int i) { return 3 & ( p >> M[i] ); }//取第i位 inline int setP(int i, int k) { return k << M[i]; }//第i位置为k inline int cntSP(int p, int cnt = 0) {//独立插头数量 for ( ; p ; p >>= 2 ) cnt += ( ( p & 3 ) == 3 ); return cnt; } inline int getLP(int p, int j) {//找对应的左括号 for ( int it = j - 1 , cnt = 1 ; ; it -- ) { int Pi = getP(p, it); if ( Pi == 1 ) cnt --; else if ( Pi == 2 ) cnt ++; if ( cnt == 0 ) return it; } } inline int getRP(int p, int j) {//找对应的右括号 for ( int it = j + 1 , cnt = 1 ; ; it ++ ) { int Pi = getP(p, it); if ( Pi == 2 ) cnt --; else if ( Pi == 1 ) cnt ++; if ( cnt == 0 ) return it; } } inline void checkmax(int &a, const int &b) { if ( a < b ) a = b; } struct HashMap { int Chart[HSize] , dp[HSize] , MSK[HSize] , next[HSize] , sz; void clear() { sz = 0; memset(Chart, -1, sizeof( Chart )); } inline void push(int msk, int val) { int x = msk % HSize; for ( int it = Chart[x] ; it != -1 ; it = next[it] ) { if ( MSK[it] == msk ) { checkmax(dp[it], val); return; } } MSK[sz] = msk; dp[sz] = val; next[sz] = Chart[x]; Chart[x] = sz ++; } } HM[2] , *src , *des; int PlugDP() { src = HM; des = src + 1; src->clear(); src->push(0, 0); int ret = 0; for ( int i = 0 ; i < n ; i ++ ) { for ( int k = 0 ; k < src->sz ; k ++ ) src->MSK[k] <<= 2; for ( int j = 0 ; j < m ; j ++ ) { if ( !vis[i][j] ) continue; checkmax(ret, maze[i][j]); des->clear(); for ( int k = 0 ; k < src->sz ; k ++ ) { int msk = src->MSK[k]; int val = src->dp[k] + maze[i][j]; int left = getP(msk, j); int up = getP(msk, j + 1); if ( !left && !up ) { des->push(msk, src->dp[k]);//能走但不走 if ( vis[i][j + 1] && vis[i + 1][j] ) des->push(msk | setP(j, 1) | setP(j + 1, 2), val); if ( cntSP(msk) > 1 ) continue; if ( vis[i + 1][j] ) des->push(msk | setP(j, 3), val); if ( vis[i][j + 1] ) des->push(msk | setP(j + 1, 3), val); } else if ( !left || !up ) { int w = left + up; int temp = CP(msk, j, j + 1); if ( vis[i + 1][j] ) des->push(temp | setP(j, w), val); if ( vis[i][j + 1] ) des->push(temp | setP(j + 1, w), val); if ( w != 3 && cntSP(msk) <= 1 ) { int it = ( w == 1 ) ? getRP(msk, j+1) : getLP(msk, j); des->push(CP(temp, it) | setP(it, 3), val); } else if ( w == 3 && temp == 0 ) checkmax(ret, val); } else if ( left == up ) { if ( left < 3 ) { int it = ( left == 1 ) ? getRP(msk, j+1) : getLP(msk, j); des->push(CP(msk, j, j + 1, it) | setP(it, left), val); } else if ( CP(msk, j, j + 1) == 0 ) checkmax(ret, val); } else if ( left == 3 || up == 3 ) { int it = ( left + up - 3 == 1 ) ? getRP(msk, j+1) : getLP(msk, j); des->push(CP(msk, j, j + 1, it) | setP(it, 3), val); } else if ( left == 2 && up == 1 ) des->push(CP(msk, j, j + 1), val); } swap(src, des); } } return ret; } int main() { for ( int i = 0 ; i < 10 ; i ++ ) M[i] = ( i << 1 ); int T; scanf("%d", &T); while ( T -- ) { scanf("%d%d", &n, &m); for ( int i = 0 ; i < n ; i ++ ) for ( int j = 0 ; j < m ; j ++ ) scanf("%d", &maze[i][j]); if ( n < m ) { for ( int i = 0 ; i < n ; i ++ ) for ( int j = i + 1 ; j < m ; j ++ ) swap(maze[i][j], maze[j][i]); swap(n, m); } memset(vis, false, sizeof( vis )); for ( int i = 0 ; i < n ; i ++ ) for ( int j = 0 ; j < m ; j ++ ) if ( maze[i][j] ) vis[i][j] = true; printf("%d\n", PlugDP()); } return 0; }