Sicily 1217. 国王的勇士

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;
}                                 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值