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;
}

浙公网安备 33010602011771号