第二届“传智杯”全国大学生IT技能大赛(决赛同步)

T130013 游园会盖章

题目描述

传智专修学院举办了一场游园活动,其中一个非常重要的环节就是收集印章。集章卡是一张高度宽度分别为 \(h,w(20\le h \le 1000,50\le w \le 2000)\) 的白纸。初始情况下每个单位像素都是由 . 来填充(代表白色)。

现在小 A 在一个摊位上盖章。由于小 A 很喜欢这个摊位印章的样式,所以他会连续盖上 \(n(1\le n \le 2000)\) 次印。这个印章是宽 50、高 20 的图形,是这样:

...........................,]]OOO@@@@OOO]`........
....................,]OO@@@@@@@@@@@@@@@@@@@@O`....
................./O@@@@@@@@@@@@@@@@@@@@@@@@@@@@^..
............../O@@@@@@@@@@@@@@@OOOOOOO@@@@@@@@@@@.
..........,/@@@@@@@@@@@@O/[.............[O@@@@@@@\
........,O@@@@@@@@@@O/`..................,O@@@@@@O
.......O@@@@@@@@@O`......]OO@@@O\`........O@@@@@@@
.....,O@@@@@@@@/`.....]O@@@@@@@@@@^.......O@@@@@@@
...,/@@@@@@@O/...../@@@@@@@@@@@@@@O....../@@@@@@@0
..=@@@@@@@O`...../@@@@@@@@@@@@@@@@^.....O@@@@@@@O.
./@@@@@@@/......O@@@@@@@@@@@@@@@O`..../@@@@@@@@O..
=@@@@@@@O......O@@@@@@@@@@@@@@@^....O@@@@@@@@@O...
O@@@@@@@^.....=@@@@@@@@@@@@@O[..../@@@@@@@@@O`....
@@@@@@@O.......\@@@@@@@@O[...../O@@@@@@@@@O`......
@@@@@@@@^.........[`.......]OO@@@@@@@@@@O`........
O@@@@@@@@O\............]/@@@@@@@@@@@@O/...........
=@@@@@@@OOOoo`........O@@@@@@@@@@@@/`.............
..\OOOOO*,`*..........O@@@@@@@@@O`................
.....,[[..............O@@@@@@O`...................
......................O@@@@@@O....................

由于盖章时手不太稳,所以盖章时也有可能会使这个图样旋转 180°(当然不同的字符只代表不同的颜色,字符本身不需要翻转)。

现在已经知道了小 A 的 \(n\) 次盖章信息,包括左上角坐标 \(x,y\),和旋转方式 \(r\)。也就是说,这个图样旋转后的左上角,位于集章卡的第 \(x\)\(y\) 列的位置,集章卡的左上角坐标是 \((0,0)\)

需要特别注意的是,后盖的印章可能和之前改的印章重叠。后盖的章有颜色的部分(不是 . 的部分)会覆盖之前印上的图形。

输入格式

第一行三个整数 \(n,h,w\) 代表印章次数,代表集章卡的高度和宽度。

接下来 \(n\) 行,每行三个整数 \(x,y,r\),描述每次盖章的信息。其中 \((x,y)\) 是图样(旋转后)左上角的坐标,\(r(0\le r\le 1)\) 代表旋转方式,代表图样顺时针旋转 \(r\times 180\degree\)。保证印章的图案至少有一部分在集章卡内部。

输出格式

输出一个高度为 \(h\),宽度为 \(w\) 的字符矩阵,表示全部盖印后的集章卡的样子。评测时会忽略行末空格和输出文件末尾的回车。

输入

2 37 70
2 2 0
15 18 1

输出

......................................................................
......................................................................
.............................,]]OOO@@@@OOO]`..........................
......................,]OO@@@@@@@@@@@@@@@@@@@@O`......................
.................../O@@@@@@@@@@@@@@@@@@@@@@@@@@@@^....................
................/O@@@@@@@@@@@@@@@OOOOOOO@@@@@@@@@@@...................
............,/@@@@@@@@@@@@O/[.............[O@@@@@@@\..................
..........,O@@@@@@@@@@O/`..................,O@@@@@@O..................
.........O@@@@@@@@@O`......]OO@@@O\`........O@@@@@@@..................
.......,O@@@@@@@@/`.....]O@@@@@@@@@@^.......O@@@@@@@..................
.....,/@@@@@@@O/...../@@@@@@@@@@@@@@O....../@@@@@@@0..................
....=@@@@@@@O`...../@@@@@@@@@@@@@@@@^.....O@@@@@@@O...................
.../@@@@@@@/......O@@@@@@@@@@@@@@@O`..../@@@@@@@@O....................
..=@@@@@@@O......O@@@@@@@@@@@@@@@^....O@@@@@@@@@O.....................
..O@@@@@@@^.....=@@@@@@@@@@@@@O[..../@@@@@@@@@O`......................
..@@@@@@@O.......\@@@@@@@@O[...../O@@@O@@@@@@O........................
..@@@@@@@@^.........[`.......]OO@@@@@`O@@@@@@O..............[[,.......
..O@@@@@@@@O\............]/@@@@@@@`O@@@@@@@@@O..........*`,*OOOOO\....
..=@@@@@@@OOOoo`........O@@@@@@`/@@@@@@@@@@@@O........`ooOOO@@@@@@@=..
....\OOOOO*,`*..........O@@@@/O@@@@@@@@@@@@/]............\O@@@@@@@@O..
.......,[[..............O@`O@@@@@@@@@@OO].......`[.........^@@@@@@@@..
........................`O@@@@@@@@@O/.....[O@@@@@@@@\.......O@@@@@@@..
......................`O@@@@@@@@@/....[O@@@@@@@@@@@@@=.....^@@@@@@@O..
.....................O@@@@@@@@@O....^@@@@@@@@@@@@@@@O......O@@@@@@@=..
....................O@@@@@@@@/....`O@@@@@@@@@@@@@@@O....../@@@@@@@/...
...................O@@@@@@@O.....^@@@@@@@@@@@@@@@@/.....`O@@@@@@@=....
..................0@@@@@@@/......O@@@@@@@@@@@@@@/...../O@@@@@@@/,.....
..................@@@@@@@O.......^@@@@@@@@@@O].....`/@@@@@@@@O,.......
..................@@@@@@@O........`\O@@@OO]......`O@@@@@@@@@O.........
..................O@@@@@@O,..................`/O@@@@@@@@@@O,..........
..................\@@@@@@@O[.............[/O@@@@@@@@@@@@/,............
...................@@@@@@@@@@@OOOOOOO@@@@@@@@@@@@@@@O/................
....................^@@@@@@@@@@@@@@@@@@@@@@@@@@@@O/...................
......................`O@@@@@@@@@@@@@@@@@@@@OO],......................
..........................`]OOO@@@@OOO]],.............................
......................................................................
......................................................................

解题思路

模拟

先将白纸初始化,再模拟覆盖即可~
注意:章的.不会覆盖

  • 时间复杂度:\(O(100\times n)\)

代码

#include<bits/stdc++.h>
using namespace std;
char paper[1005][2005];
char stamp[25][55]=
{
"...........................,]]OOO@@@@OOO]`........",
"....................,]OO@@@@@@@@@@@@@@@@@@@@O`....",
"................./O@@@@@@@@@@@@@@@@@@@@@@@@@@@@^..",
"............../O@@@@@@@@@@@@@@@OOOOOOO@@@@@@@@@@@.",
"..........,/@@@@@@@@@@@@O/[.............[O@@@@@@@\\",
"........,O@@@@@@@@@@O/`..................,O@@@@@@O",
".......O@@@@@@@@@O`......]OO@@@O\\`........O@@@@@@@",
".....,O@@@@@@@@/`.....]O@@@@@@@@@@^.......O@@@@@@@",
"...,/@@@@@@@O/...../@@@@@@@@@@@@@@O....../@@@@@@@0",
"..=@@@@@@@O`...../@@@@@@@@@@@@@@@@^.....O@@@@@@@O.",
"./@@@@@@@/......O@@@@@@@@@@@@@@@O`..../@@@@@@@@O..",
"=@@@@@@@O......O@@@@@@@@@@@@@@@^....O@@@@@@@@@O...",
"O@@@@@@@^.....=@@@@@@@@@@@@@O[..../@@@@@@@@@O`....",
"@@@@@@@O.......\\@@@@@@@@O[...../O@@@@@@@@@O`......",
"@@@@@@@@^.........[`.......]OO@@@@@@@@@@O`........",
"O@@@@@@@@O\\............]/@@@@@@@@@@@@O/...........",
"=@@@@@@@OOOoo`........O@@@@@@@@@@@@/`.............",
"..\\OOOOO*,`*..........O@@@@@@@@@O`................",
".....,[[..............O@@@@@@O`...................",
"......................O@@@@@@O...................."
};
int n,h,w,x,y,r;
int main()
{
    for(int i=0;i<=1000;i++)
        for(int j=0;j<=2000;j++)paper[i][j]='.';
    for(scanf("%d%d%d",&n,&h,&w);n;n--)
    {
        scanf("%d%d%d",&x,&y,&r);
        if(r==0)
        {
            for(int i=x;i<min(1001,x+20);i++)
                for(int j=y;j<min(2001,y+50);j++)
                    if(stamp[i-x][j-y]!='.')paper[i][j]=stamp[i-x][j-y];
        }
        else
        {
            for(int i=x;i<min(1001,x+20);i++)
                for(int j=y;j<min(2001,y+50);j++)
                    if(stamp[x-i+19][y-j+49]!='.')paper[i][j]=stamp[x-i+19][y-j+49];
        }
    }
    for(int i=0;i<h;i++)
    {
        for(int j=0;j<w;j++)putchar(paper[i][j]);
        puts("");
    }
    return 0;
}

P6462 补刀

题目描述

UIM 在写程序的空闲玩一款 MOBA 游戏。

image

当敌方的小兵进入到我方防御塔的范围内,就会持续受到防御塔造成的伤害;当然我方英雄也可以对它造成伤害。当小兵的血量降到了 0 或者更低,就会被击杀。为了获得经验,UIM 希望在防御塔将这个小兵杀死之前,亲自补刀将其击杀。

为了简化问题,我们假设这个小兵有 \(h\) 点的生命值。每次防御塔的攻击可以给小兵造成 \(x\) 点伤害,而你的英雄每次攻击可以给小兵造成 \(y\) 点伤害。你的攻击速度和防御塔攻击速度相同,所以你可以在防御塔第一次攻击小兵之前,或者每次防御塔攻击之后,选择是否对小兵进行一次攻击,当然你也可以选择不攻击。

现在想知道,给出这些信息,判断英雄是否有办法将这个小兵击杀?

输入格式

每个测试点由多组数据组成。

输入第一行,包含一个正整数 \(T\),表示数据组数。

接下来 \(T\) 行,每行三个非负整数 \(h,x,y\),其意义已经在题目描述中给出。

输出格式

输出 \(T\) 行。对于每组数据,如果可以最后将小兵击杀,输出 Yes,否则输出 No

输入

5
100 100 1
100 97 1
100 98 1
100 99 1
100 100 0

输出

No
No
Yes
Yes
No

说明/提示

数据的组数不多于 \(50\)\(1\le h \le 10^{18}\)\(0\le x,y \le 10^{18}\)

解题思路

模拟

先特判如果英雄输出不小于小兵血量,可以补刀。如果英雄输出为 \(0\),则肯定补不了刀;否则如果防御塔输出为 \(0\),则可以补刀
假设防御塔攻击了小兵 \(a\) 次,如果 \((a+1) \times y \ge h-a\times x\),则说明可以补刀,求出满足条件的最小的 \(a\),同时需要满足 \(h-a \times x >0\),即小兵被防御塔攻击后还有血量剩余~

  • 时间复杂度:\(O(t)\)

代码

#include<bits/stdc++.h>
using namespace std;
using LL=long long;
int t;
LL h,x,y;
int main()
{
    for(scanf("%d",&t);t;t--)
    {
        scanf("%lld%lld%lld",&h,&x,&y);
        if(y==0)puts("No");
        else if(x==0)
            puts("Yes");
        else
        {
            if(y>=h)puts("Yes");
            else
            {
                LL a=(h-y+x+y-1)/(x+y);
                puts(h-a*x>0?"Yes":"No");
            }
        }
    }
    return 0;
}

P6464 传送门

题目描述

传智专修学院里有 \(n\) 栋教学楼,有 \(m\) 条双向通行道路连接这些教学楼,不存在重边和自环。每条道路都有一定的长度,而且所有教学楼之间都可以直接或者间接的通过道路到达。我们可以很容易的求出这些教学楼之间的最短路。

为了使交通更为顺畅,校方决定在两个教学楼里增设一对传送门。传送门可以将这对教学楼的距离直接缩短为 \(0\)。利用传送门,某些教学楼之间的最短路的距离就变短了。

由于预算有限,学校里只能安装一对传送门。但是校长希望尽可能方便学生,使任意两点之间的最短路长度的总和最小。当然啦,从 \(x\) 教学楼到 \(y\) 教学楼的长度和从 \(y\) 教学楼到 \(x\) 教学楼的长度只需要统计一次就可以了。

输入格式

输入第 \(1\) 行两个正整数 \(n,m(n\le 100,m\le\frac{1}{2}n(n-1))\),代表教学楼和道路数量。

接下来 \(m\) 行,每行三个正整数 \(x_i,y_i,w_i(0 <w_i \le 10^4)\),表示在教学楼 \(x_i\)\(y_i\) 之间,有一条长度为 \(w_i\) 的道路。

输出格式

输出一行,在最优方案下的任意点对的最短道路之和。

输入

4 5
1 2 3
1 3 6
2 3 4
2 4 7
3 4 2

输出

14

说明/提示
image

样例如图。当在 \(1\)\(4\) 号教学楼架设一对传送门时,\(1 → 2\) 的最短路是 \(3\)\(1 → 3\) 的最短路是 \(0+2\)\(1 → 4\) 的最短路是 \(0\)\(2 → 3\) 的最短路是 \(4\)\(2 → 4\) 的最短路是 \(3+0\)\(3 → 4\) 的最短路是 \(2\),最短路之和是 \(14\),是最佳方案。

解题思路

floyd

先用floyd求出全源最短路,再枚举任意两个教学楼放置传送门,再次使用floyd更新答案,此时只用 \(O(n^2)\) 的复杂度更新经过这两个教学楼的最短路即可~

  • 时间复杂度:\(O(n^4)\)

代码

//floyd
#include<bits/stdc++.h>
using namespace std;
int n,m,x,y,w,d[105][105],bd[105][105];
int main()
{
    scanf("%d%d",&n,&m);
    memset(d,0x3f,sizeof d);
    for(int i=1;i<=n;i++)d[i][i]=0;
    while(m--)
    {
        scanf("%d%d%d",&x,&y,&w);
        d[x][y]=d[y][x]=w;
    }
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
    int res=0x3f3f3f3f;
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        {
            memcpy(bd,d,sizeof d);
            bd[i][j]=bd[j][i]=0;
            for(int k=1;k<=n;k++)
                for(int t=1;t<=n;t++)
                    bd[k][t]=min(bd[k][t],bd[k][i]+bd[i][t]);
            for(int k=1;k<=n;k++)
                for(int t=1;t<=n;t++)
                    bd[k][t]=min(bd[k][t],bd[k][j]+bd[j][t]);
            int s=0;
            for(int k=1;k<=n;k++)
                for(int t=k+1;t<=n;t++)
                    s+=bd[k][t];
            res=min(res,s);
        }
    printf("%d",res);
    return 0;
}
posted @ 2021-11-02 20:40  zyy2001  阅读(98)  评论(0编辑  收藏  举报