USACO 4.4.3 Frame Up 重叠的图像 题解与分析

来源:互联网 发布:防9158聊天室源码 编辑:程序博客网 时间:2024/06/11 15:48

Frame Up 重叠的图像

译 by Felicia Crazy


描述

看下面的五张 9 x 8 的图像:

........   ........   ........   ........   .CCC....EEEEEE..   ........   ........   ..BBBB..   .C.C....E....E..   DDDDDD..   ........   ..B..B..   .C.C....E....E..   D....D..   ........   ..B..B..   .CCC....E....E..   D....D..   ....AAAA   ..B..B..   ........E....E..   D....D..   ....A..A   ..BBBB..   ........E....E..   DDDDDD..   ....A..A   ........   ........E....E..   ........   ....AAAA   ........   ........EEEEEE..   ........   ........   ........   ........  1          2           3          4          5

现在,把这些图像按照 1—5 的编号从下到上重叠,第 1 张在最下面,第 5 张在最顶端。如果一张图像覆盖了另外一张图像,那么底下的图像的一部分就变得不可见了。我们得到下面的图像:

             .CCC....             ECBCBB..             DCBCDB..             DCCC.B..             D.B.ABAA             D.BBBB.A             DDDDAD.A             E...AAAA             EEEEEE..

对于这样一张图像,计算构成这张图像的矩形图像从底部到顶端堆叠的顺序。

下面是这道题目的规则:

  • 矩形的边的宽度为 1 ,每条边的长度都不小于 3 。
  • 矩形的每条边中,至少有一部分是可见的。注意,一个角同时属于两条边。
  • 矩形用大写字母表示,并且每个矩形的表示符号都不相同。

格式

PROGRAM NAME: frameup

INPUT FORMAT:

(file frameup.in)

第一行 两个用空格分开的整数:图像高 H (3 <= H <=30) 和图像宽 W (3 <= W <= 30) 。

第二行到第 H+1 行 H 行,每行 W 个字母。

OUTPUT FORMAT

(file frameup.out)

按照自底向上的顺序输出字母。如果有不止一种情况,按照字典顺序输出每一种情况(至少会有一种合法的顺序)。

SAMPLE INPUT

9 8.CCC....ECBCBB..DCBCDB..DCCC.B..D.B.ABAAD.BBBB.ADDDDAD.AE...AAAAEEEEEE..

SAMPLE OUTPUT

EDABC
【分析】:
   首先对于每种字符,会组成不同矩形,统计这些矩形的左上角<即最左值和最上值>,右上角<即最右值和最下值>,然后建图:若本来在该矩形的边上存在不同于该矩形的字符,则将该矩形和不同于该矩形的字符对应的矩形编号连一条有向边,然后跑一边拓扑排序,注意,不同的拓扑序可能造成答案不同,因此用DFS来枚举所有拓扑序而不仅仅只跑一遍,最后对答案排序,输出即可
【时间复杂度】:
   设字符种类为kind,则建图过程复杂度为O(kind*H*W),统计入度O(kind*kind),拓扑排序O(kind*kind*kind)
【代码】:
/*   ID:csyzcyj1   PROG:frameup   LANG:C++*/#include<stdio.h>#include<string.h>#include<stdlib.h>#include<algorithm>#include<iostream>#include<vector>#include<stack>#include<queue>#include<map>using namespace std;#define MAX 31#define MAXN 101#define IMAX 21474836struct rectangle{      int l,r,u,d;      void reset(){l=IMAX,r=0,u=IMAX,d=0;}};rectangle a[MAX];int H,W,kind=0,indegree[MAXN];char in[MAX][MAX];bool visin[MAXN],map1[MAX][MAX],vis[MAXN];map<char,int> number;map<int,char> word;map<string,bool> hash;string empty;vector<string> ans;void pre_group(){      for(int i=1;i<=kind;i++)      {            for(int j=a[i].l;j<=a[i].r;j++)            {                  if(in[a[i].u][j]!=word[i] && in[a[i].u][j]!='.')                        map1[i][number[in[a[i].u][j]]]=true;                  if(in[a[i].d][j]!=word[i] && in[a[i].d][j]!='.')                        map1[i][number[in[a[i].d][j]]]=true;                              }            for(int j=a[i].u;j<=a[i].d;j++)            {                  if(in[j][a[i].l]!=word[i] && in[j][a[i].l]!='.')                        map1[i][number[in[j][a[i].l]]]=true;                  if(in[j][a[i].r]!=word[i] && in[j][a[i].r]!='.')                        map1[i][number[in[j][a[i].r]]]=true;                              }      }      for(int i=1;i<=kind;i++)            for(int j=1;j<=kind;j++)                  if(map1[i][j])                       indegree[j]++;                                    }void topsort(int floor,string now){      if(floor==kind+1 && !hash[now])      {            hash[now]=true;            ans.push_back(now);            return;      }      for(int i=1;i<=kind;i++)      {            if(indegree[i]==0 && !vis[i])            {                   vis[i]=true;                   indegree[i]=-1;                   for(int j=1;j<=kind;j++)                         if(map1[i][j])                               indegree[j]--;                   topsort(floor+1,now+(char)word[i]);                   for(int j=1;j<=kind;j++)                         if(map1[i][j])                               indegree[j]++;                   indegree[i]=0;                   vis[i]=false;            }      }}int main(){      freopen("frameup.in","r",stdin);  freopen("frameup.out","w",stdout);   scanf("%d%d",&H,&W);      for(int i=1;i<=H;i++)      {            scanf("\n");            for(int j=1;j<=W;j++)            {                  scanf("%c",&in[i][j]);                  if(!visin[in[i][j]] && in[i][j]!='.')                  {                        kind++;                        visin[in[i][j]]=true;                        number[in[i][j]]=kind;                        word[kind]=in[i][j];                        a[number[in[i][j]]].reset();                  }                                    a[number[in[i][j]]].l=min(j,a[number[in[i][j]]].l);                  a[number[in[i][j]]].r=max(j,a[number[in[i][j]]].r);                  a[number[in[i][j]]].u=min(i,a[number[in[i][j]]].u);                  a[number[in[i][j]]].d=max(i,a[number[in[i][j]]].d);            }      }      pre_group();      topsort(1,empty);      sort(ans.begin(),ans.end());      for(int i=0;i<(int)ans.size();i++)            cout<<ans[i]<<endl;  //system("pause");      return 0;}
【评测信息】:
        TASK: frameup
        LANG: C++
        Compiling...
        Compile: OK
        Executing...
        Test 1: TEST OK [0.011 secs, 3524 KB]
        Test 2: TEST OK [0.011 secs, 3524 KB]
        Test 3: TEST OK [0.011 secs, 3524 KB]
        Test 4: TEST OK [0.011 secs, 3524 KB]
        Test 5: TEST OK [0.011 secs, 3524 KB]
        Test 6: TEST OK [0.011 secs, 3524 KB]
        Test 7: TEST OK [0.011 secs, 3524 KB]
        Test 8: TEST OK [0.205 secs, 3656 KB]
        Test 9: TEST OK [0.454 secs, 3920 KB]
        All tests OK.

        YOUR PROGRAM ('frameup') WORKED FIRST TIME!

        That's fantastic-- and a rare thing. Please accept these special automatedcongratulations.

 

转载注明出处:http://blog.csdn.net/u011400953

 
原创粉丝点击