【♂Not The Triumph♂O(∩_∩)O哈哈~But The Struggle♂】

竞赛决不是捷径,它只是另一种艰辛的生活方式。得到与失去,只有时间会去评判;成功与失败,只有历史能去仲裁。我不会永远成功,正如我不会永远失败一样

  C++博客 :: 首页 :: 联系 ::  :: 管理
  6 Posts :: 239 Stories :: 25 Comments :: 0 Trackbacks

常用链接

留言簿(7)

我参与的团队

搜索

  •  

积分与排名

  • 积分 - 108422
  • 排名 - 229

最新评论

阅读排行榜

评论排行榜

看下面的五张 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.ABAA
D.BBBB.A
DDDDAD.A
E...AAAA
EEEEEE..

SAMPLE OUTPUT
EDABC

分析: 
   首先,把每个矩形的上下左右边界统统记录下来。这样,沿每一个矩形的边走一遍,就可以知道谁压着它了。用一个数组cover记录谁压着谁。其实就是个有向无回路图。
   然后,拓扑排序。因为是要的所有解,所以要回溯法全找出来。
   计算拓扑序列时有两种方法:
   1.“删点法”,每次删去一个入度为0的点和它出发的所有边。删点的顺序就是一个拓扑序列。
   2.把有向图中所有的边反过来,再DFS,遍历完一个结点的子树后输出这个点。不过有个缺点,就是题目要求按字母顺序输出所有解,但这种方法最后还要排序。(我选择的第一种)

【参考程序】:

/*
ID: XIONGNA1
PROG: frameup
LANG: C++
*/
#include
<stdio.h>
#include
<string.h>
#include
<stdlib.h>
int up[40],down[40],left[40],right[40];
int f[40],into[40],ans[40];
bool bo[40],cover[40][40];
char a[40][40];
int h,w,num;
void tuopsort(int k)
{
    
if (k==num+1)
    {
        
for (int i=1;i<=num;i++)
            printf(
"%c",char(ans[i]+64));
        printf(
"\n"); return ;
    }
    
for (int i=1;i<=num;i++)
        
if (into[i]==0)
        {
            into[i]
=32767; ans[k]=f[i];
            
for (int j=1;j<=num;j++)
                
if (cover[f[j]][f[i]]) into[j]--;
            tuopsort(k
+1);
            into[i]
=0;
            
for (int j=1;j<=num;j++)
                
if (cover[f[j]][f[i]]) into[j]++;
        }
}
int main()
{
    freopen(
"frameup.in","r",stdin);
    freopen(
"frameup.out","w",stdout);
    scanf(
"%d%d",&h,&w); getchar();
    memset(up,
0x7F,sizeof(up));
    memset(left,
0x7F,sizeof(left));
    memset(down,
0,sizeof(down));
    memset(right,
0,sizeof(right));
    memset(bo,
false,sizeof(bo));
    
int k;
    
for (int i=1;i<=h;i++)
    {
        
for (int j=1;j<=w;j++)
        {
            scanf(
"%c",&a[i][j]);
            
if (a[i][j]=='.'continue;
            k
=(a[i][j]-64); bo[k]=true;
            
if (i<up[k]) up[k]=i;
            
if (i>down[k]) down[k]=i;
            
if (j<left[k]) left[k]=j;
            
if (j>right[k]) right[k]=j;
        }
        getchar();
    }
    memset(cover,
false,sizeof(cover));
    num
=0;
    
for (int c=1;c<=26;c++)
        
if (bo[c])
        {
            num
++; f[num]=c;
            
for (int i=up[c];i<=down[c];i++)
            {
                
if ((a[i][left[c]]-64)!=c)
                    cover[a[i][left[c]]
-64][c]=true;
                
if ((a[i][right[c]]-64)!=c)
                    cover[a[i][right[c]]
-64][c]=true;
            }
            
for (int i=left[c];i<=right[c];i++)
            {
                
if ((a[up[c]][i]-64)!=c)
                    cover[a[up[c]][i]
-64][c]=true;
                
if ((a[down[c]][i]-64)!=c)
                    cover[a[down[c]][i]
-64][c]=true;
            }
        }
    memset(into,
0,sizeof(into));
    
for (int i=1;i<=num;i++)
        
for (int j=1;j<=num;j++)
            
if (cover[f[i]][f[j]]) into[i]++;
    tuopsort(
1);
    
return 0;
}
posted on 2009-08-02 13:30 开拓者 阅读(306) 评论(0)  编辑 收藏 引用 所属分类: USACO 题解

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理