ZOJ 3474 Taekwondo

7 篇文章 0 订阅
Taekwondo

Time Limit: 2 Seconds       Memory Limit: 65536 KB

Alice is very fond of Taekwondo and he is also a member of Taekwondo Association of Zhejiang University. One day, his friends decide to compare with him. Now Alice must face all of his friends'challange, that is to say, if there are T friends, then he will take T matchs in just one day! Of course Alice has limited energe power, so he must carefully arrange the order of the T matchs and take optional strategy to win all the matchs.

Here are the rules of taekwondo match. Player must use available kicks to hit available position of his opponent's body. Different kick gets different points. To simplify this problem, we assume that Alice will use only 3 kinds of kicks, as shown below:

  1. Axe Kick:consume P1 energe power, get 3 points
  2. Back-Whirling Kick: consume P2 energe power, get 2 points
  3. Turning Kick: consum P3 energe power, get 1 points
P 1 P 2 P 3  depends on the opponent and will be given in the input. For example, if the opponent is taller than Alice, then Axe Kick may consume more energe, but for a shorter opponent, it will be easier to use Axe Kick,thus consuming less energe.

If Alice wants to win a single match, he must get at least 7 points and guarantee that his enenge is above zero. After each match, Alice will have a chance to rest, and will recover R energe power, Ralso depends on different opponent. Alice's initial energe power is S , and after a rest, his energe power may be more than S, which is available. Remember that Alice can freely arrange the order of all the matches and he must win all the matches.

Input

The first line of the input is a single integer m, which is the number of test cases. In each case, fisrt there are two integers T (T≤22) and S (S≤100), indicating that there are T friends to compare with Alice and Alice's initial energe power is S. the following T lines each contain 4 integers: Pi1Pi2Pi3Ri, as described above. (0<=Pi1Pi2Pi3Ri≤100)

Output

For each case, you should output one line. If Alice can win all the matches, output the max energe power he can save at last. Otherwise,output "no".

Sample Input
2
2 100
40 40 40 100
20 70 10 100
1 10
40 40 40 100

Sample Output
130
no
Hint

In case 1, Alice should compare with the second person first, consume 50 energe power (2 Axe Kick and 1 Turning Kick), recover 100, then compare with the first person, consume 120 (2 Axe Kick and 1 Turning Kick), recover 100, thus the answer is 130.


贪心,感觉是一个很好的题,WA了很多遍,最后参考的其他人的思路才AC的

关键点在于其与对手的比赛顺序的选择上,单纯的按最小消耗值或是体力恢复值或是二者的大小差值排序是不正确的,为保证其能和更多个对手比赛,应该先处理净体力值为正值的选手(就是比完后体力的恢复值减去其最小消耗值为正值),可以按其消耗值从小向大排列,这样可以保证一遍将净体力值为正值的对手全比完(前提是可以与对手进行比赛,否则体力不足跳出),然后再处理为负的值,为负的值则按回复值的由大至小进行排列,至于为什么这样排请参考某大神证明过程http://hi.baidu.com/aekdycoin/item/8249c815f31c3ef9756a84dc

代码如下:

#define test
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>

using namespace std;

struct power
{
    int p1, p2, p3, r;
} team[24];
struct point
{
    int r, con;
} add[24], de[24];
int r_cmp(const void *a, const void *b)
{

    point *aa = (point *)a;
    point *bb = (point *)b;
    return aa->r < bb->r ? 1 : -1;
}
int con_cmp(const void *a, const void *b)
{

    point *aa = (point *)a;
    point *bb = (point *)b;
    return aa->con > bb->con ? 1 : -1;
}
int differ(int i) // 数据量较小,可以枚举所有情况判断最小消耗值
{
    int _min=0x7FFFFFFF, a, b, c;
    for(a=0; a <= 3; a++)
        for(b=0; b <= 4; b++)
            for(c=0; c <= 7; c++)
                if(a*3 + b*2 + c >= 7)
                    _min = min(_min,c*team[i].p3 + b*team[i].p2 + a*team[i].p1);

    return _min;
}
int flag[24], s;
int main()
{
#ifdef test
    freopen("in.txt", "r", stdin);
#endif
    int m, t;
    scanf("%d", &m);
    while(m--)
    {
        int add_i = 0, de_i = 0;
        scanf("%d%d", &t, &s);
        for(int i = 1; i <= t; i++)
        {
            scanf("%d%d%d%d", &team[i].p1, &team[i].p2, &team[i].p3, &team[i].r);
            int ans = differ(i);
            if(team[i].r - ans >= 0)
            {
                add[add_i].r = team[i].r;
                add[add_i++].con = ans;
            }
            else
            {
                de[de_i].r = team[i].r;
                de[de_i++].con = ans;
            }
        }
        qsort(add, add_i, sizeof(add[0]), con_cmp); // 净体力恢复值为正的按消耗值从小到大排序
        qsort(de, de_i, sizeof(de[0]), r_cmp);  // 净体力恢复值为负的按恢复值从大到小排序
        int ok = 1;
        for(int i = 0;ok && i < add_i; i++)
        {
            if(s <= add[i].con)  // 若不满足条件,则跳出返回0,挑战失败
                ok = 0;
            s += add[i].r - add[i].con;
        }
        for(int i = 0; ok && i < de_i; i++)
        {
            if(s <= de[i].con)
                ok = 0;
            s += de[i].r - de[i].con;
        }
        if(ok)
            printf("%d\n", s);
        else
            printf("no\n");
    }
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值