Section 4.4 frameup

/*
ID: niepeng1
PROG: frameup
LANG: C++
*/
/*
 类似拓扑排序问题,easy。
 统计矩形的最左,最右,最上,最下。
 并统计矩形的遮挡关系,记录下来。
 (在该矩形的四个边上,如果有不同的字母
 ,则记录为该矩形被字母矩形遮挡。)
 然后每一次输出一个没有被其他矩形遮挡的矩形
 ,取消已经输出的矩形对剩余矩形的遮挡,注意此
 处需要逆向输出,于是把遮挡关系反着记录,于
 是输出时就不用排序了。题目猥琐,方法巧妙。
*/
#include<stdio.h>
#include<memory.h>
#include<algorithm>
char a[32][32];
int h,w,count=0;
bool in[27]={false},yet[27];
int pos[27][4];
bool over[32][32];
char ans[27];

void Out(int num)
{
 int i,j;
 if( num == count){
  ans[count]=0;
   printf("%s",ans);
  printf("/n");
  return;
 }
 for(i=0;i<26;i++){
  if(yet[i]||!in[i])//如果访问过了,或者该字母根本就不在图里面跳过
   continue;
  for(j=0;j<26;j++)
   if(!yet[j] && over[i][j] )
    break;//如果存在遮挡关系,放弃
  if(j >=26)//如果没有遮挡输出,记录,标记访问过了
  {
   yet[i]=true;
   ans[num]=i+'A';
   Out(num+1);
   yet[i]=false;
  }
 }
}
int main()
{
 freopen("frameup.in","r",stdin);
 freopen("frameup.out","w",stdout);
 int i,j;
 scanf("%d %d",&h,&w);
 for(i=0;i<h;i++)
 {
  scanf("%s",&a[i]);
 }
 
 for(i=0;i<h;i++)
  for(j=0;j<w;j++)
  {
   if( a[i][j]<='Z' && a[i][j]>='A'){
    if(in[a[i][j]-'A']==false){//碰到新矩形
     count++;
     in[a[i][j]-'A']=true;
     pos[a[i][j]-'A'][0]=pos[a[i][j]-'A'][1]=i;
     pos[a[i][j]-'A'][2]=pos[a[i][j]-'A'][3]=j;
    }
    else{
     if(pos[a[i][j]-'A'][0]>i) pos[a[i][j]-'A'][j]=i;//记录矩形的四个边
     if(pos[a[i][j]-'A'][1]<i) pos[a[i][j]-'A'][1]=i;
     if(pos[a[i][j]-'A'][2]>j) pos[a[i][j]-'A'][2]=j;
     if(pos[a[i][j]-'A'][3]<j) pos[a[i][j]-'A'][3]=j;
    }
   }
  }
 memset(over,false,sizeof(over));
 for(i=0;i<26;i++){//记录遮挡关系
  if(in[i]==false)
   continue;
  for(j=pos[i][2];j<=pos[i][3];j++){
   if( a[pos[i][0]][j]<='Z' && a[pos[i][0]][j] >= 'A' && a[pos[i][0]][j]-'A'!=i )
    over[a[pos[i][0]][j]-'A'][i]=true;
   if( a[pos[i][1]][j]<='Z' && a[pos[i][1]][j] >= 'A' && a[pos[i][1]][j]-'A'!=i )
    over[a[pos[i][1]][j]-'A'][i]=true;
  }
  for(j=pos[i][0];j<=pos[i][1];j++){
   if( a[j][pos[i][2]]<='Z' && a[j][pos[i][2]] >= 'A' && a[j][pos[i][2]]-'A'!=i)
    over[a[j][pos[i][2]]-'A'][i]=true;
   if( a[j][pos[i][3]]<='Z' && a[j][pos[i][3]] >= 'A' && a[j][pos[i][3]]-'A'!=i)
    over[a[j][pos[i][3]]-'A'][i]=true;
  }
 }
 memset(yet,false,sizeof(yet));
 Out(0);
 return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值