第二届“传智杯”全国大学生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 游戏。
当敌方的小兵进入到我方防御塔的范围内,就会持续受到防御塔造成的伤害;当然我方英雄也可以对它造成伤害。当小兵的血量降到了 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
说明/提示
样例如图。当在 \(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;
}