1. 程式人生 > >2017百度之星資格賽 1003:度度熊與邪惡大魔王(DP)

2017百度之星資格賽 1003:度度熊與邪惡大魔王(DP)

solution nav normal ner 就會 預處理 display badge rate

度度熊與邪惡大魔王

Accepts: 3021 Submissions: 18787 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
http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=774&pid=1003 就是一個完全背包,每個怪獸可以分開算,最後把答案加起來就是總的答案;由於怪獸的防禦值範圍很小,可以預處理出每一組技能下打死不同生命、不同防禦值的怪物消耗的最少晶石,對於每個怪物直接在其中取答案,比對於每個怪物求一次要快很多。 自己的代碼&講解:(太醜 了,什麽一直求到2*maxa也沒誰了。。) 技術分享
 1 /*
 2 ans[i][j][b]表示防禦力為b的怪物
 3 表示用前i種技能,造成恰好j的傷害消耗的最小晶石
 4 ans[i][j][b]=min{ans[i-1][j-x*(p[i]-b)]+x*k[i]}
 5 x表示第i種技能取x個(0<=x*(p[i]-b)<=j)
 6 優化:http://blog.csdn.net/wumuzi520/article/details/7014830
 7 ans[i][j][b]=min(ans[i-1][j][b],ans[i][j-(p[i]-b)][b]+k[i]【j>=p[i]-b】)
 8 =>ans[j][b]=min(ans[j][b],ans[j-(p[i]-b)][b]+k[i] **i從小到大
 9 */
10 #include<cstdio>
11 #include<cstring>
12 #include<algorithm>
13 using namespace std;
14 typedef long long LL;
15 LL n,m;
16 LL maxb,maxp,bx,maxa;
17 LL a[100100],b[100100];
18 LL ans[10001][11];
19 LL k[1010],p[1010],ans1;
20 int main()
21 {
22     LL i,j,t,ze=(long long)0;
23     while(scanf("%lld%lld",&n,&m)==2)
24     {
25         maxb=0;maxp=0;maxa=0;
26         for(i=1;i<=n;i++)
27         {
28             scanf("%lld%lld",&a[i],&b[i]);
29             maxb=max(maxb,b[i]);
30             maxa=max(maxa,a[i]);
31         }
32         for(i=1;i<=m;i++)
33         {
34             scanf("%lld%lld",&k[i],&p[i]);
35             maxp=max(maxp,p[i]);
36         }
37         maxa=max(maxa,maxp);
38         /*
39         去掉以上這句,會讓類似
40         1 1
41         45 10
42         4164 327
43         的數據得出錯誤結果
44         */
45         if(maxb>=maxp)
46         {
47             printf("-1\n");
48             continue;
49         }
50         memset(ans,0x3f,sizeof(ans));
51         memset(ans[0],0,sizeof(ans[0]));
52         for(bx=0;bx<=maxb;bx++)
53         {
54             for(i=1;i<=m;i++)
55                 for(j=max(ze,p[i]-bx);j<=2*maxa;j++)
56             //    {
57                     //if(j>=p[i]-bx)
58                         ans[j][bx]=min(ans[j][bx],ans[j-p[i]+bx][bx]+k[i]);
59             //    }
60             t=0x3f3f3f3f;
61             for(j=2*maxa;j>=0;j--)
62             {
63                 t=min(t,ans[j][bx]);
64                 ans[j][bx]=min(ans[j][bx],t);
65             }
66         }
67         ans1=0;
68         for(i=1;i<=n;i++)
69             ans1+=ans[a[i]][b[i]];
70         printf("%lld\n",ans1);
71         
72         
73     }
74     return 0;
75 }
View Code

2017百度之星資格賽 1003:度度熊與邪惡大魔王(DP)

2017百度之星資格賽 1003:度度熊與邪惡大魔王(DP)