USACO第一场模拟赛の小结

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为真的个数就是可能为第一个涂的颜色的个数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值