POJ 3600 Subimage Recognition 枚举+递归
http://poj.org/problem?id=3600
题意:给出一个小矩形,每个格子有黑白两种状态,再给出一个大矩形,每个格子也有两种状态,从大矩形去掉一些行和列后能否形成小矩行(r,c<=20)
开始的思路就是 行递归选择行,再列递归选择列 那就是2^400中情况 肯定会超时
cxl提供的一个可行的巧妙的思路就是 枚举小矩形的第一行在大矩形中的位置(比如在大矩形的第k行) 然后递归在大矩形中选择N(小矩形的列数)然后从K行开始
能否找到小矩形的对应行。。。这样就一次递归2^20次方是可以接受的
代码:
#include<iostream> #include<cstdio> #include<string> #include<cstring> using namespace std; int Min[22][22],Max[22][22]; int col[22]; int r1,c1,r2,c2; int k,cnt; bool fg; bool check() { int i,j,r=1; for(i=k;i<=r2;i++) { for(j=1;j<=c1;j++) if(Min[r][j]!=Max[i][col[j]])break; if(j>c1){r++;if(r>r1)break;} } if(r==(r1+1))return 1; return 0; } void dfs(int x) { if(cnt>c1) { fg=check(); return ; } if(x>c2)return ; col[cnt++]=x; dfs(x+1); if(fg)return ; cnt--; dfs(x+1); } int main() { int i,j; char ch; while(cin>>r1>>c1)//~scanf("%d%d",&n1,&m1) { for(i=1;i<=r1;i++) for(j=1;j<=c1;j++) { cin>>ch; Min[i][j]=ch-'0'; } cin>>r2>>c2; for(i=1;i<=r2;i++) for(j=1;j<=c2;j++) { cin>>ch; Max[i][j]=ch-'0'; } fg=0; for(k=1;k<=r2-r1+1;k++)//!!! { if(fg)break; cnt=1; dfs(1); } if(fg)printf("Yes\n"); else printf("No\n"); } return 0; }