1217. 国王的勇士
Constraints
Time Limit: 5 secs, Memory Limit: 32 MB
Description
在很久很久以前,两个古老的王国之间发生了冲突。为了避免战争带来血流成河的场面,双方的国王决定派出各自国内的勇士进行一对一的决斗,来分出胜负。由于两个王国都有着无数的勇士,所以为了公平起见,大家约定决斗若干场,最后获胜次数多的一方就是胜利者。
每个勇士都有姓名,最大生命力,当前生命力,攻击力,防御力和恢复能力六项数据。勇士的姓名都是各不相同的,而后五种能力统一用整数来度量。当当前生命力等于最大生命力的时候,我们称这名勇士的生命力是满的。
为了保证决斗有秩序的进行,双方协商制定了一个决斗规则:
1.决斗采用回合制,即决斗的双方轮流的攻击。为了表现礼仪,姓名字典序靠后的都会让姓名字典序靠前的先攻。
2.当A攻击B时,A对B造成的伤害值x就等于A的攻击力减去B的防御力。若这一伤害值小于10,就将x当作10来计算。也就是说,最少造成10点的伤害。在A攻击过后,B的当前生命力就减少x。
3.决斗一直进行到某一方的当前生命力小于或等于0时停止,此时另一方为胜利者。当然,决斗的双方是友好的,胜利者不会杀掉失败者。
4.双方勇士在决斗结束的第二天开始慢慢的恢复当前生命力,直到生命力满了为止。胜利的一方从决斗后的当前生命力开始恢复,输的一方从0开始恢复。当前生命力恢复的速度由恢复能力决定,为了使问题简单化,我们假定恢复能力的数值表示在每天结束时恢复多少点生命力。
5.每一天最多只进行一场决斗。
在每场决斗之前,双方的国王会约定一个决斗的时间,然后各自派出一名勇士。国王有两种方法派遣勇士:
1.指定一名勇士的姓名
2.选择当前生命力为满的且战斗能力最强的一名。战斗能力的计算公式为:最大生命力*0.2+攻击力*0.8+防御力*0.6,若有相同的,选择姓名字典序靠前的一位。假定至少会有一名生命力为满的勇士。
为了纪念双方为了避免战争所做出的努力,一位史学家记录下来了所有勇士的数据以及国王们的每一个指令,现在要求你求出每一场决斗的结果以及最终的胜负情况。
Input
前两行分别是两个王国的名字。
接着一行为一个整数n1(1<=n1<=2000),然后是第一个王国中n1个勇士的数据。每个勇士的数据占一行,格式为:
姓名 最大生命力 攻击力 防御力 恢复能力
一开始所有的勇士生命力都是满的。姓名是长度不超过10的字符串,第一个字母为大写,其他的都由小写字母组成。除姓名外都是10000以内的正整数。
接下来一行为一个整数n2(1<=n2<=2000),之后n2行是第二个王国中n2个勇士的数据。
再下一行是一个奇数q(1<=q<100000),表示决斗的次数,下面是q个决斗的信息。每个决斗有一个时间占一行,格式为:
年/月/日
年是不超过1000的正整数,日期一定是合法的。
接着两行分别是两个国王各自的指令。可以是直接选择勇士,格式为:
王国名 勇士名
或者选择生命力为满的且战斗能力最强的勇士,格式为:
王国名 choose strongest
输入保证选取的勇士一定存在,且所有的决斗按时间顺序给出。
Output
对于每一场决斗,输出两行:
Winner:王国名 勇士名
Loser:王国名 勇士名
并在最后用两行输出最终的结果:
Winner:王国名
Loser:王国名
Sample Input
Greece Rome 3 Zeus 756 900 650 200 Athena 500 560 980 120 Prometheus 800 900 320 320 3 Jupiter 620 780 610 200 Venus 1000 320 650 40 Mars 800 1000 500 420 3 20/1/1 Greece choose strongest Rome choose strongest 20/1/2 Rome Jupiter Greece Athena 20/5/4 Greece Prometheus Rome choose strongest
Sample Output
Winner:Greece Zeus Loser:Rome Mars Winner:Rome Jupiter Loser:Greece Athena Winner:Rome Mars Loser:Greece Prometheus Winner:Rome Loser:Greece
Problem Source
ZSUACM Team Member
// Problem#: 1217
// Submission#: 3586328
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <stdio.h>
#include <string.h>
#include <algorithm>
//#include <stdlib.h>
using namespace std;
#define maxwarriors 2000
#define maxstrlen 13
long day;
class WARRIOR {
public:
char name[maxstrlen];
long maxlife, attack, defense, resume;
long skill, life, life_time, ok_time;
long id;
bool operator < (const WARRIOR & that) const {
return strcmp(name, that.name) < 0;
}
void cal_life() {
if (life == maxlife) {
life_time = day;
return;
}
life += resume * (day - life_time - 1);
if (life > maxlife) life = maxlife;
life_time = day;
}
void damage(long d) {
life -= d;
if (life < 0) life = 0;
ok_time = life_time + (maxlife - life + resume - 1) / resume + 1;
}
};
bool skillcmp(WARRIOR * w1, WARRIOR * w2) {
if (w1->skill != w2->skill) return w1->skill > w2->skill;
else return strcmp(w1->name, w2->name) < 0;
}
/*
int sort_skill(const void * a, const void * b) {
long i;
i = (*(WARRIOR**)b)->skill - (*(WARRIOR**)a)->skill;
if (i > 0) i = 1;
if (i < 0) i = -1;
if (i == 0) {
if (strcmp((*(WARRIOR**)a)->name, (*(WARRIOR**)b)->name) > 0) i = 1;
else i = -1;
}
return i;
}
*/
class KING {
public:
char kingname[maxstrlen];
long n;
WARRIOR w[maxwarriors];
long win_times;
long chosed;
WARRIOR * id_skill[maxwarriors];
void init_warriors() {
scanf("%ld", &n);
for (int i = 0; i < n; i++) {
scanf("%s%ld%ld%ld%ld", w[i].name, &w[i].maxlife, &w[i].attack, &w[i].defense, &w[i].resume);
w[i].skill = w[i].maxlife * 2 + w[i].attack * 8 + w[i].defense * 6;
w[i].life = w[i].maxlife;
w[i].life_time = w[i].ok_time = 0;
}
sort(w, w + n);
for (int i = 0; i < n; i++) {
id_skill[i] = &w[i];
w[i].id = i;
}
sort(id_skill, id_skill + n, skillcmp);
//qsort(&(id_skill[0]), n, sizeof(id_skill[0]), sort_skill);
}
void init() {
long i;
init_warriors();
win_times = 0;
}
void chose() {
char s[100];
long i;
WARRIOR tmp;
scanf("%s", s);
if (strcmp(s, "choose") == 0) {
scanf("%*s");
for (i = 0; i < n; i++) if (id_skill[i]->ok_time <= day) break;
chosed = id_skill[i]->id;
} else {
strcpy(tmp.name, s);
chosed = lower_bound(w, w + n, tmp) - w;
}
}
};
void battle(KING * pa, KING * pb) {
WARRIOR * wa, * wb, * tmp;
KING * mid;
long damage1, damage2, times1, times2, times1_r, times2_r;
wa = &pa->w[pa->chosed];
wa->cal_life();
wb = &pb->w[pb->chosed];
wb->cal_life();
if (!((*wa) < (*wb))) {
mid = pa;
pa = pb;
pb = mid;
tmp = wa;
wa = wb;
wb = tmp;
}
damage1 = wa->attack - wb->defense;
if (damage1 < 10) damage1 = 10;
damage2 = wb->attack - wa->defense;
if (damage2 < 10) damage2 = 10;
times1 = (wb->life + damage1 - 1) / damage1;
times2 = (wa->life + damage2 - 1) / damage2;
if (times1 <= times2) {
pa->win_times++;
times1_r = times1;
times2_r = times1 - 1;
printf("Winner:%s %s\nLoser:%s %s\n", pa->kingname, wa->name, pb->kingname, wb->name);
} else {
pb->win_times++;
times1_r = times2;
times2_r = times2;
printf("Winner:%s %s\nLoser:%s %s\n", pb->kingname, wb->name, pa->kingname, wa->name);
}
wa->damage(times2_r * damage2);
wb->damage(times1_r * damage1);
}
KING a, b;
KING * pa, * pb;
long m;
long years_days[1001];
long month_days[2][12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool leap(long year) {
return (year % 100 != 0 && year % 4 == 0) || year % 400 == 0;
}
long get_day(char date[]) {
long i, j, k, y, m, d, re;
for (i = 0; date[i]; i++) if (date[i] == '/') date[i] = ' ';
sscanf(date, "%ld%ld%ld", &y, &m, &d);
if (y == 0) re = 0;
else re = years_days[y - 1];
k = leap(y);
for (i = 1; i < m; i++) re += month_days[k][i - 1];
return re + d;
}
int main() {
char date[100], s[100];
years_days[0] = 365 + leap(0);
for (int i = 1; i <= 1000; i++) years_days[i] = years_days[i - 1] + 365 + leap(i);
scanf("%s%s", &a.kingname, &b.kingname);
a.init();
b.init();
scanf("%ld", &m);
while (m--) {
scanf("%s", date);
day = get_day(date);
scanf("%s", s);
if (strcmp(s, a.kingname) == 0) {
pa = &a;
pb = &b;
} else {
pa = &b;
pb = &a;
}
pa->chose();
scanf("%*s");
pb->chose();
battle(pa, pb);
}
if (a.win_times > b.win_times) printf("Winner:%s\nLoser:%s\n", a.kingname, b.kingname);
else printf("Winner:%s\nLoser:%s\n", b.kingname, a.kingname);
int qwe;
scanf("%d", &qwe);
return 0;
}