T322082 顶级理解
题目背景
昊昊作为游戏大神,游戏时长上千小时,拥有顶级理解,准备用一级号裸装单挑boss.
题目描述
该boss只有一个技能:(模仿大师)
玩家每攻击一次就会记忆玩家招式及伤害;
每被打掉100血,会模仿出招,将最近3次的伤害反弹到玩家身上,并遗忘这3次招式。(不足3次的话,将最近的伤害全都反弹)
作为有顶级理解的高级玩家,昊昊决定用1级号,靠站撸(不闪避)打败boss。
boss血量�u, 玩家血量�v, n次攻击�1,�2...��a1,a2...an。 由于是新手裸装,攻击力不会超过99(��<100ai<100)
问昊昊能否在n次攻击内打败boss。
如果打败boss输出'Yes',并输出玩家还剩的血量
如果N次攻击后没有打败boss输出'No',并输出boss还剩的血量
如果中途被boss打死输出'gg',并输出boss还剩的血量
输入格式
第一行输入�,�,�u,v,n(boss血量,玩家血量,攻击次数)
第二行输入�1,�2,...��a1,a2,...an
输出格式
如果打败boss输出'Yes',并输出玩家还剩的血量
如果�n次攻击后没有打败boss输出'No',并输出boss还剩的血量
如果中途被boss打死输出'gg',并输出boss还剩的血量
(空格隔开)
题目解析
注意每达到100攻击后,boss会反击,但攻击只会减少100,不会清零
eg:50 60 90
在第二次打击后cc==110;反击,cc-=100; c=10, c+=90==100;第三次再反击
还有招式也是不会全部清零,而是每次反击后面三个,不够三个就全部反击,这样才会清零
eg:20 20 20 20 20 达到100后反击后三个招,剩下 20 20
代码
#include<iostream>
#define F(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
int aa[1010];
int main()
{
int u, v, n;
cin >> u >> v >> n;
int cc = 0;//打击总伤害
bool tf = 0;//用于判断是否boss死了,或者玩家死了
int idx = 1;//数列模仿栈
F(i, 1, n)
{
cin >> aa[idx];//伤害
cc += aa[idx];//总伤害更新
u -= aa[idx];//boss血量减少
if (u <= 0)//boss死了
{
cout << "Yes" <<" " << v;
tf = 1;
break;
}
if (cc >= 100)//每达到100打击,反击
{
cc -= 100;
if (idx >= 3)//分三类
{
v -= aa[idx] + aa[idx - 1] + aa[idx - 2];
idx -= 3;
}
else if (idx == 2)
{
v -= aa[idx] + aa[idx - 1];
idx -= 2;
}
else if(idx==1)
{
v -= aa[idx];
idx -= 1;
}
if (v <= 0)//玩家是否死了
{
cout << "gg" <<" " << u;
tf = 1;
break;
}
}
idx++;//每次都要++,模仿栈
}
if (tf == 0)//都没死
cout << "No" << " "<<u;
return 0;
}
T322022 Ltree的数据结构
题目描述
成绩处于[G,100]的同学会获得50元饭票,处于[60,G)的同学会获得20元饭票同时Ltree还会把总评成绩前 K 名的学生列入优秀学生名单。本题就请你编写程序,帮助Ltree列出优秀学生,并统计一共发出了面值多少元的 饭票。
输入格式
输入在第一行给出 3 个整数,分别是 N(不超过 10 000 的正整数,为学生总数)、G(在 (60,100) 区间内的整数,为题面中描述的代金券等级分界线)、K(不超过 100 且不超过 N 的正整数,为进入优秀学生名单的最低名次)。
接下来 N 行,每行给出一位学生的账号(长度不超过15位、不带空格的字符串)和总评成绩(区间 [0, 100] 内的整数),其间以空格分隔。题目保证没有重复的账号。
输出格式
输出一行为饭票的总价值,接下来K行按照学生成绩的非升序进行排序,输出学生的排名,账号,成绩,用一个空格分隔,成绩相同的学生排名并列,并列时按照账号字典序升序排列输出。
输入 #1复制
10 80 5
1001@qq.com 65
test@126.com 39
zoe@mit.edu 80
bob@cmu.edu 80
ken@163.com 70
输出 #1复制
360
1 uh-oh@163.com 96
2 jack@ucla.edu 88
3 anyone@qq.com 87
3 cy@pat-edu.com 87
5 bob@cmu.edu 80
5 zoe@mit.edu 80
解析
饭钱过于简单,不说了,讲结构体排名
主要看样例,同个分数占据同一个排名,但也会影响下面的排名,如样例,两个3名,没有第四名;
我们可以以aa[k].cou 排在k名的同学分数作为最低分数,比他大才有机会
如何实现上面的同位次排名呢?还有隔位排名呢?
int sc = aa[k].cou;//能进排名的最低分(用了结构体)
for (int i = 1; aa[i].cou >= sc; ++i)//能进排名的最低分,大于才能循环
{
if (aa[i].cou != aa[i - 1].cou)//若和上一位不同分,更新为真实排名
aa[i].idx = i;
else //若和上一名同分,即继承上一位的排名,若很多同分也可一直继承
aa[i].idx = aa[i-1].idx;
}
整体代码
#include<iostream>
#include<cstring>
#include<algorithm>
#define F(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
struct kkk
{
int idx;//排名
string str;//名字
int cou;//分数
}aa[10010];//数组形式
long long sum = 0;
bool cmp(kkk a,kkk b)//sort排序
{
if (a.cou > b.cou)
return 1;
else if (a.cou < b.cou)
return 0;
else//同分
{
if (a.str < b.str)
return 1;
else
return 0;
}
}
int main()
{
int n, g, k;
cin >> n >> g >> k;
for (int i = 1; i <= n; ++i)
{
cin >> aa[i].str;
cin >> aa[i].cou;
}
sort(aa + 1, aa + 1 + n, cmp);
for (int i = 1; i <= n; ++i)//饭钱
{
if (aa[i].cou >= g)
sum += 50;
else if (aa[i].cou >= 60)
sum += 20;
}
cout << sum << endl;
int sc = aa[k].cou;//能进排名的最低分
for (int i = 1; aa[i].cou >= sc; ++i)
{
if (aa[i].cou != aa[i - 1].cou)
aa[i].idx = i;
else
aa[i].idx = aa[i-1].idx;
}
for (int i = 1; aa[i].cou>=sc; ++i)
{
cout << aa[i].idx<< " " << aa[i].str << " " << aa[i].cou << endl;
}
return 0;
}