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

  

posted @ 2012-04-14 09:22  快乐.  阅读(171)  评论(0编辑  收藏  举报