poj_1288_回溯

来源:互联网 发布:淘宝手机端首页模版 编辑:程序博客网 时间:2024/05/17 12:48

题目描述:  

  就是给一系列frame(字母构成的矩形边框,一个frame为一个大写字母组成的边框)。然后给一张图(矩形阵列),该图是fame按照某个次序往上覆盖的结果显示。

 

解题思路:

  回溯。注意的地方比较多,首先是结果图的存储问题,需要记录争取的字母框四条边位置;其次是回溯的思路,从顶层开始找符合条件的frame,直到最底层;最后是字典序输出问题,这个题理论上26个字母最大结果是不够存的,不过这个题的测试数据似乎开1000也就可以了。

  几个小错误地方:(1)字符串清空(2)多组输入!  

 

代码:

#include <stdio.h>
#include <stdlib.h>
#define N 31
#define MAX 1000

typedef struct
{
   intleft,right,top,bottom;
   char c;
}LETTER;

LETTER l[27], letter[27];
int f[N],flag[27],count,r,h,w,result[27],g;
char str[N][N],s[MAX][27];

int testFrame(int t)
{
   int i,j;
   inttt=letter[t].top,b=letter[t].bottom,l=letter[t].left,r=letter[t].right;

   i=tt;
  for(j=l;j<=r;j++)                 
    if((flag[str[i][j]-'A'] == 0) &&(str[i][j] != letter[t].c))
       return 0;
   i=b;
  for(j=l;j<=r;j++)                 
    if((flag[str[i][j]-'A'] == 0) &&(str[i][j] != letter[t].c))
       return 0;
   j=l;
  for(i=tt+1;i<b;i++)
    if((flag[str[i][j]-'A'] == 0) &&(str[i][j] != letter[t].c))
       return 0;
   j=r;
  for(i=tt+1;i<b;i++)
    if((flag[str[i][j]-'A'] == 0) &&(str[i][j] != letter[t].c))
       return 0;
    return1;
}

void try(int num)
{
   int i;
  if(num>count)
   {
     for(i=count;i>=1;i--)
        s[g][count-i] = letter[result[i]].c;
     g++;
   }
   else
   {
     for(i=count;i>=1;i--)//从顶层开始找
      
        if((0 == flag[letter[i].c-'A'])&&(testFrame(i) == 1))//该点未被检查过且是一个frame
        {
           flag[letter[i].c-'A'] = 1;
           result[r] = i;
           r++;
           try(num+1);
           r--;
           flag[letter[i].c-'A'] =0;      
        }
     }
   }
}
int cmp ( const void *a , const void *b )
{
    returnstrcmp((char *)a ,(char *)b);
}

main()
{
   int i,j;
  
   while(scanf("%d%d",&h,&w)!=EOF)
   {
      //input
      for(i=0;i<h;i++)
         scanf("%s",str[i]);
      //遍历
      for(i=0;i<26;i++)
         f[i] = 0;
      
      for(i=0;i<h;i++)
         for(j=0;j<w;j++)
         {
            if(str[i][j] >='A'&&str[i][j]<='Z')
            {
               if(f[str[i][j]-'A']==0) //未记录过
               {
                  l[str[i][j]-'A'].c = str[i][j];
                  l[str[i][j]-'A'].left = j;
                  l[str[i][j]-'A'].right = j;
                  l[str[i][j]-'A'].top = i;
                  l[str[i][j]-'A'].bottom = i;
                  f[str[i][j]-'A'] = 1;
               }
               else
               {
                  if( j < l[str[i][j]-'A'].left)
                     l[str[i][j]-'A'].left = j;
                  if( j > l[str[i][j]-'A'].right)
                     l[str[i][j]-'A'].right = j;
                  if( i > l[str[i][j]-'A'].bottom)
                     l[str[i][j]-'A'].bottom = i;
               }
            }
         }
      count = 0;
      //数一共几个。并按次序记录。
      for(i=0;i<26;i++)
         if(f[i]!=0)
         {
             count ++;
             letter[count] = l[i];//复制到letter里。按次序,前count个。
         }
      for(i=0;i<26;i++)
            flag[i] = 0;
      r=1;
      memset(s,0,sizeof(s));
      g=0;
      try(1);
      qsort(s,g,sizeof(s[0]),cmp);//排序s[],一共g个(0->g-1)
      for(i=0;i<g;i++)
         printf("%s\n",s[i]);
  
   //system("pause");
   return 0;
  
}