USACO第一场模拟赛の小结

来源:互联网 发布:最新软件毕业设计题目 编辑:程序博客网 时间:2024/06/10 03:00

10.25

(USACO铜组三题)

我已经发了两题的博客,一题是失去的母牛,另一题是牛的基因组学,现在还有一题现代艺术。
现代艺术
题目描述:
世界各地的艺术评论家直到现在才开始意识到伟大的牛画家Bibi的创意天赋。
Bibi用一种特殊的方式绘画。她用一块N*N的画布开始画画 “0”表示一个画布的空单元格。然后她在画布上画了9个矩形。她会使用9种颜色的一种(为了方便(Bibi是个很懒的人),她把颜色编号为1~9). 她每次可以选择任意一种未使用过的颜色进行绘画。
举个例子,如果她从颜色2开始画,下面是她画画的过程:
2220
2220
2220
0000

然后她可能画了一个颜色为7的矩形:
2220
2777
2777
0000

随后她画了一个颜色为3的小矩形:
2230
2737
2777
0000

每一个矩形的边都是平行于边缘的,鉴于画布的最终状态,请计算出画布上有多少种颜色可能是第一次被画上去的。(矩形的大小是不确定的  可能是一个单元格  也可能覆盖整个画布)

输入格式(文件名:art.in)

第一行是整数n(1<=n<=10)下面n*n的矩阵由数字0~9组成,描述的是最后完成的画布。

输出格式(文件名 art.out)

输出一个整数 表示最终画布的颜色中,可能为第一个画上去的颜色个数。

样例输入:
4
2230
2737
2777
0000

样例输出:
1

样例解释:在本例中,只有颜色2可能是第一个被绘制的。颜色3显然是在颜色7之后画的,而颜色7显然是在颜色2之后画的。

代码

#include<bits/stdc++.h>using namespace std;int n,s=0;char a[15][15];string tmp;bool b[15]={},c[15][15];int main(){    freopen("art.in","r",stdin);    freopen("art.out","w",stdout);    scanf("%d",&n);    getline(cin,tmp);    for (int i=1;i<=n;++i)    {        for (int j=1;j<=n;++j)        {            scanf("%c",&a[i][j]);            b[a[i][j]-'0']=true;        }        getline(cin,tmp);    }    for (int i=1;i<=9;++i)    if (b[i])    {        int x=100,y=100,xx=0,yy=0;        for (int j=1;j<=n;++j)        for (int k=1;k<=n;++k)        if (a[j][k]-'0'==i)        {            x=min(x,j);            y=min(y,k);            xx=max(xx,j);            yy=max(yy,k);        }        for (int j=x;j<=xx;++j)        for (int k=y;k<=yy;++k)        if (a[j][k]-'0'!=i)        c[i][a[j][k]-'0']=true;    }    for (int i=1;i<=9;++i)    if (b[i])    {        bool flag=true;        for (int j=1;j<=9;++j)        if (c[j][i]) flag=false;        if (flag) s++;    }    cout<<s<<endl;    return 0;}

思路
先输入这个方阵,用a二维字符数组存储,然后我用b一维数组来存储哪些颜色出现过。中间的循环是主体,循环的目的是:找到每一个出现过的颜色的最大矩形,然后在这个最大矩形里开始搜索,寻找跟它不同的颜色。这里有一个玄学操作,这是我听了一位神一般的大佬的方法后才AC的。——用一个c二维数组来标记涂颜色的顺序,左端点比右端点先涂标记为真,这样,哪些颜色先涂,哪些颜色后涂就很清楚了。之后的那一个循环,目的是:找到每一个出现过的颜色,如果它比其它颜色后涂,那么它肯定不是第一个涂的颜色,flag标记为假。最后统计flag为真的个数就是可能为第一个涂的颜色的个数。

原创粉丝点击