1. 程式人生 > >簡單典型貪心---(解題報告)HDU4310---Hero

簡單典型貪心---(解題報告)HDU4310---Hero

Hero

Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3379 Accepted Submission(s): 1516

Problem Description
When playing DotA with god-like rivals and pig-like team members, you have to face an embarrassing situation: All your teammates are killed, and you have to fight 1vN.

There are two key attributes for the heroes in the game, health point (HP) and damage per shot (DPS). Your hero has almost infinite HP, but only 1 DPS.

To simplify the problem, we assume the game is turn-based, but not real-time. In each round, you can choose one enemy hero to attack, and his HP will decrease by 1. While at the same time, all the lived enemy heroes will attack you, and your HP will decrease by the sum of their DPS. If one hero’s HP fall equal to (or below) zero, he will die after this round, and cannot attack you in the following rounds.

Although your hero is undefeated, you want to choose best strategy to kill all the enemy heroes with minimum HP loss.

Input
The first line of each test case contains the number of enemy heroes N (1 <= N <= 20). Then N lines followed, each contains two integers DPSi and HPi, which are the DPS and HP for each hero. (1 <= DPSi, HPi <= 1000)

Output
Output one line for each test, indicates the minimum HP loss.

Sample Input
1
10 2
2
100 1
1 100

Sample Output
20
201

解題思路:
1.首先是這個題的題目意思,講的是在你打遊戲時面對了以一打多的情況,這時你開了無敵狀態,有無限的生命,但是你的攻擊力變為了1,試問你把所有敵人打倒時你消耗的最少生命值;
2.很容易看出這是個最簡單的貪心問題,貪心思想的體現:將DFS與HP的比值進行從大到小的排序,然後按這個順序依次打。
3. 這裡我有一點分析,當排好序後,怎麼很快的寫出打怪時的程式碼,我覺得應該首先分析的是那些量在打的時候是變化的,然後找出這些變化的量之間的聯絡,分析出程式碼,在這個題中變化的是受到傷害的總數(即你最後要輸出的數),然後是剩下總的人數(這裡主要體現在每打一個人之後剩下的攻擊力也即你下一輪會受到的傷害),這樣很輕鬆就可以想出程式碼;

程式碼如下:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef struct data
{
    double DFS;
    double HP;
    double comp;
}data;
int cmp(data x,data y)
{             
    return x.comp>y.comp;
}
int main()
{
    int n;
    data a[50];
    while(cin>>n&&n)
    {
        int i,sum=0,
        allDFS=0,
        afterDFS=0;
        memset(a,0,sizeof(a));
        for(i=0;i<n;i++)
        {
            cin>>a[i].DFS>>a[i].HP;
            a[i].comp=a[i].DFS/a[i].HP;       //貪心思想的體現:將DFS與HP的比值進行從大到小的排序,然後按這個順序依次打。 
            allDFS+=a[i].DFS;
        }
        sort(a,a+n,cmp); 
        for(i=0;i<n;i++)                //打怪時的程式碼,注意是一個敵人一個敵人的打,關鍵是分析在打的過程中那些量是變化的,然後找出其聯絡,就可以很順的寫出程式碼了。 
        {
            sum+=(allDFS-afterDFS)*a[i].HP;    //此時變化的是受到傷害的總數;   
            afterDFS+=a[i].DFS;    //這裡變化的是死去英雄的攻擊力;用總的攻擊力減去死去英雄的攻擊力的和就是打下一個英雄時受到的單次攻擊力; 
        }
        cout<<sum<<endl;
    }
    return 0;
}

僅代表個人觀點,不喜勿噴,歡迎交流!!!
這裡寫圖片描述