2017百度之星資格賽—1003度度熊與邪惡大魔王
度度熊與邪惡大魔王
題目傳送門
Accepts: 3608 Submissions: 22145
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Problem Description
度度熊為了拯救可愛的公主,於是與邪惡大魔王戰鬥起來。
邪惡大魔王的麾下有n個怪獸,每個怪獸有a[i]的生命值,以及b[i]的防禦力。
度度熊一共擁有m種攻擊方式,第i種攻擊方式,需要消耗k[i]的晶石,造成p[i]點傷害。
當然,如果度度熊使用第i個技能打在第j個怪獸上面的話,會使得第j個怪獸的生命值減少p[i]-b[j],當然如果傷害小於防禦,那麼攻擊就不會奏效。
如果怪獸的生命值降為0或以下,那麼怪獸就會被消滅。
當然每個技能都可以使用無限次。
請問度度熊最少攜帶多少晶石,就可以消滅所有的怪獸。
Input
本題包含若干組測試資料。
第一行兩個整數n,m,表示有n個怪獸,m種技能。
接下來n行,每行兩個整數,a[i],b[i],分別表示怪獸的生命值和防禦力。
再接下來m行,每行兩個整數k[i]和p[i],分別表示技能的消耗晶石數目和技能的傷害值。
資料範圍:
1<=n<=100000
1<=m<=1000
1<=a[i]<=1000
0<=b[i]<=10
0<=k[i]<=100000
0<=p[i]<=1000
Output
對於每組測試資料,輸出最小的晶石消耗數量,如果不能擊敗所有的怪獸,輸出-1
Sample Input
1 2
3 5
7 10
6 8
1 2
3 5
10 7
8 6
Sample Output
6
18
其他題目就不發部落格了(有些也沒做出來!!),感覺這次百度之星資格賽題目資料有毒,吐槽,其他題目也不好說,感覺這個題目正常點。
這個題目我當時想到的就是動態規劃,但是評論中很多人說是貪心,我一直不理解,認為他們對於貪心和動態規劃之間的範疇沒有搞清楚(可能是我沒搞清楚!有錯誤請dalao指正),可能有dalao能貪心出來(一臉敬佩);雖然知道是動態規劃問題,可轉移方程怎麼搞?我一直在想(比較弱!!),想了許多的動態規劃的方法,還是用打表的方式(就是每種可能出現的怪獸,根據這組資料的技能和傷害值,用陣列記錄它消耗的最小晶石數目),這樣全部出來了就方便了,將出現的怪獸消耗的最小晶石數目加起來即可;比賽開始一個小時才AC這個題目,一發AC(比較開心),有dalao有更好的方法請賜教(萬分感謝!!)。
AC程式碼:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const long long INF=1e15;
const int maxn=100000+10;
const int maxm=1000+10;
struct P{
int live;//怪獸的生命值
int figth;//怪獸的防禦力
}p[maxn];
struct V{
int money;//技能的消耗晶石數目
int shai;//技能的傷害值
}v[maxm];
long long ans[maxm][15];//儲存每種怪獸需要消耗的最小晶石數目
int n,m;
bool cmpp(P a,P b)
{
return a.figth>b.figth;//以怪獸的防禦力從大到小排序
}
bool cmpv(V a,V b)
{
return a.shai>b.shai;//以技能的傷害值從大到小排序
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
int i,j,k;
for(i=0;i<n;i++)
{
scanf("%d%d",&p[i].live,&p[i].figth);
}
for(i=0;i<m;i++)
{
scanf("%d%d",&v[i].money,&v[i].shai);
}
sort(p,p+n,cmpp);
sort(v,v+m,cmpv);
if(p[0].figth>=v[0].shai)
//當怪獸的最大防禦力大於等於技能的最大傷害值,不可能消滅全部怪獸
{
printf("-1\n");
continue;
}
else
{
fill(&ans[0][0],&ans[0][0]+maxm*15,INF);
//初始每種怪獸都需要消耗無窮大晶石數目,因為是取最小值
for(i=0;i<=10;i++)
ans[0][i]=0;
//當怪獸的生命值為0時,消耗0晶石
for(i=1;i<=1000;i++)
{
for(j=0;j<=10;j++)
{
for(k=0;k<m;k++)
{
int s=v[k].shai;
if(s>=i+j)
s=i;
else
{
if(s<=j)
s=0;
else
s-=j;
}
//因為i-s不能<0,所以進行判斷賦值,i-s相當於怪獸被技能攻擊還剩餘的生命值
ans[i][j]=min(ans[i][j],ans[i-s][j]+v[k].money);
}
}
}
long long sum=0;
for(i=0;i<n;i++)
sum+=ans[p[i].live][p[i].figth];
//加上每種怪獸需要消耗的最小晶石數目
printf("%I64d\n",sum);
}
}
return 0;
}