码迷,mamicode.com
首页 > 其他好文 > 详细

“亚信科技杯”南邮第七届大学生程序设计竞赛之网络预赛 (K L题解)

时间:2015-03-30 18:24:45      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:

“亚信科技杯”南邮第七届大学生程序设计竞赛之网络预赛 (K L题解) 

 

第一次出题,果然背锅了,L题由于数据问题,让两种不对的方法ac了,分别是:H<0时取前一天送上花(应该是wa,思路错误),第二种是dfs的(应该是TLE),但是数据太小。所以,就当强行送温暖了,不过不希望误导大家,大家有空再思考思考正解~~

 

首先是K题:

法师

时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 175            测试通过 : 30 

题目描述

说到法师,也许大家第一反应便是脆弱的身躯与强大的爆发能力。诚然如此,在《炉石传说》中,法师拥有着最高伤害的单体法术——炎爆术,同时还有同样高伤害的火球术。但法师并不仅限于此,如果说这两张火系法术代表着的是法师的爆发。那么冰系法术就代表了法师的控制,冰霜新星、冰锥术以及暴风雪和寒冰箭都能够使对手冻结。

每张卡牌能造成一定的伤害,同时也要花费一定的法力水晶。当法力水晶不够的时候,你便不能打出相应的卡牌。

为了简单起见,我们只考虑以下几张卡牌。

寒冰箭 :消耗2点法力水晶,对一个角色造成3点伤害,并使其冻结。

冰枪术:消耗1点法力水晶,使一个角色冻结,如果它已经被冻结,则改为对其造成4点伤害。

火球术:消耗4点法力水晶,造成6点伤害。

炎爆术:消耗10点法力水晶,造成10点伤害。

现在,告诉你现在拥有的法力水晶,以及手上拥有的这四种卡牌的数目(可能为0),问你能对敌方英雄造成多少点伤害。


输入

 

第一行为一个正整数T,表示有T组数据。

每组数据第一行有1个整数: n表示当前拥有的法力水晶个数0<=n<=10。

第二行为四个整数a,b,c,d分别表示拥有寒冰箭、冰枪术、火球术、炎爆术的数目。0<=a,b,c,d<=10.

 

输出

 

一个整数表示最大可能造成的伤害值。

 

样例输入

2
9
0 0 3 0
5
2 2 1 1

样例输出

12
11

 

题目来源

NUPT

 

题意:

告诉你现在拥有的法力水晶(n),以及手上拥有的这四种卡牌的数目(可能为0),问你能对敌方英雄造成多少点伤害。

ps:冰冻的特效是一旦冰冻就会一直冰冻。

 

题解:

1.想作为一道水题的,不想为难大家,所以数据范围均<=10,直接四重循环暴力即可,最后判断一下关于冰冻的事情。(如果没有寒冰箭的话,要先浪费一个冰枪术)

2.如果数据范围比较大的话,暴力就会TLE,这时候,可以考虑先用背包的思路(动态规划的一种),将火球术和炎爆术进行预处理。

得到dp[i],表示使用了i点法力水晶,可以造成的最大伤害,在此基础上,考虑寒冰箭与冰枪术了。

2.1 如果剩余法力水晶充足,一起加上。

2.2 如果剩余法力不足,分为两种情况:使用寒冰箭与不使用寒冰箭。

2.2.1 不使用寒冰箭,把冰枪术的伤害加上即可。

2.2.2 使用寒冰箭,那么先拿出一张寒冰箭,然后优先用冰枪术(不涉及到冰冻问题,冰枪术的性价比要高),然后再加上寒冰箭。

 

标程:

这里先给出暴力法的标程,有兴趣的同学可以尝试一下,如果数据比较大(1<=n,a,b,c,d<=100000)的情况,如何用上述方法解决。

 

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 int main()
 5 {
 6     int T;
 7     scanf("%d", &T);
 8     while(T--)
 9     {
10         int a, b, c, d, n;
11         scanf("%d", &n);
12         scanf("%d %d %d %d", &a, &b, &c, &d);
13         int ans = 0;
14         
15             for(int i = 0; i <= a; i++)
16             {
17                 for(int j = 0; j <= b; j++)
18                 {
19                     for(int k = 0; k <= c; k++)
20                     {
21                         for(int l = 0; l <= d; l++)
22                         {
23                             if(2 * i + 1 * j + 4 * k + 10 * l <= n)
24                             {
25                                 if(i > 0) //用寒冰箭冰冻
26                                     ans = max(ans, 3 * i + 4 * j + 6 * k + 10 * l);
27                                 else
28                                 {
29                                     if(j >= 1) //用冰枪术冰冻
30                                         ans = max(ans, 4 * (j - 1) + 6 * k + 10 * l);
31                                     else
32                                         ans = max(ans, 6 * k + 10 * l);
33                                 }    
34                             }
35                         }
36                     }
37                 }
38             }
39         printf("%d\n", ans);
40     }
41 }

 

 

 

然后是L:

 

送花

时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 117            测试通过 : 42 

题目描述

萌妹纸一般都比较喜欢漂亮的鲜花。每逢各种节日,她们都想收到鲜花作为礼物。如果你是有妹纸滴人,经常不送妹纸花的话,结果可想而知了。

当然咯,妹纸都是通情达理的,不会因为某几次你木有送花,就发你好人卡了。王童鞋作为一个比较节俭(抠门)的人便知道这一道理,因此他想在妹纸不给他发好人卡的前提下,送尽量少的花。

为了简单起见,我们定义一个妹纸的幸福指数H(初始为0 )。如果某天幸福指数H小于0,那就。。。

如果某天妹纸收到了花,幸福指数H会增加ai,如果没收到,会下降bi。不同的日子送花对幸福指数的增加可能会有所不同,比如在2月14号送花就会比2月15号效果好~

即告诉你总天数n(1<=n<=365),每天收到花幸福指数的增加值ai(1<=ai<=10),没收到花幸福指数的降低值bi,求为了让妹纸的幸福指数H一直>=0,王童鞋至少要送妹纸多少朵花。


输入

 

第一行为一个正整数T,表示有T组数据。

每组数据第一行有1个整数: n表示总天数1<=n<=365。

第二行为n个整数ai表示第i天收到花幸福指数的增加值,1<=ai<=10。第三行为n个整数bi表示第i天没收到花幸福指数的下降值,1<=bi<=10。

 

输出

 

一个整数表示最少需要送多少朵花。

 

样例输入

2
1
3
4
5
5 2 10 1 1
1 1 1 5 5

样例输出

1
2

 

题目来源

NUPT

 

 

这题要和大家说抱歉了,L题由于数据问题,让两种不对的方法ac了,分别是:H<0时取前一天送上花(应该是wa,思路错误),第二种是dfs的(应该是TLE),但是数据太小。所以,就当强行送温暖了,不过不希望误导大家,大家有空再思考思考正解~~

 

题意:

告诉你总天数n(1<=n<=365),妹纸的幸福指数H初始为0,每天收到花幸福指数的增加值ai(1<=ai<=10),没收到花幸福指数的降低值bi,求为了让妹纸的幸福指数H一直>=0,王童鞋至少要送妹纸多少朵花。

 

题解:

1.本来是想出个动态规划的题目:

即每天只有两种选择,送或者不送。那么可以定义dp[i][j]含义为前i天,让妹纸的幸福值达到j所需要的最少花的数目。最后枚举一下最后一天即可。

转移方程也不难:

送花的话:dp[i][ j+a[i] ]=min(dp[i][ j+a[i] ],dp[i-1][j]+1);

不送花的话:dp[i][ j-b[i] ]=min(dp[i][ j-b[i] ],dp[i-1][j]);

 

2.这题也可以用贪心的思路,不过不是简单的,H<0时取前一天送上花。而是应该,H<0时取前面没送花的某天,如果改为送花,选择送花收益最大的一天送花。

(能让妹纸幸福值变得最大,这里的增加不是指的a[i],而是a[i]+b[i])

具体的实现可以用优先队列。如果H>=0,我们不选,H-=b[i],同时将 a[i]+b[i]的值存入优先队列。

(因为,如果这天改为送花,妹纸的幸福指数不但不会下降b[i],反而会上升a[i],一来一去收益为 a[i]+b[i])。

然后,如果h<0,将优先队列的队首元素出队列,记为temp,h+=temp

 

同样,这里只给出动态规划的标程,希望大家思考如何写出正确的贪心程序。当数据范围变成,1<=n<=100000,1<=ai<=10000,1<=bi<=10000.

 

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <stack>
 4 #include <vector>
 5 #include <algorithm>
 6 
 7 #define ll long long
 8 int const N = 405;
 9 int const M = 205;
10 int const inf = 1000000000;
11 ll const mod = 1000000007;
12 
13 using namespace std;
14 
15 int T;
16 int n;
17 int dp[N][10*N];
18 int mi;
19 int a[N];
20 int b[N];
21 int suma;
22 
23 void ini()
24 {
25     int i;
26     mi=inf;
27     suma=0;
28     scanf("%d",&n);
29     memset(dp,-1,sizeof(dp));
30     dp[0][0]=0;
31     for(i=1;i<=n;i++){
32         scanf("%d",&a[i]);
33         suma+=a[i];
34     }
35     for(i=1;i<=n;i++){
36         scanf("%d",&b[i]);
37     }
38 }
39 
40 void solve()
41 {
42     int i,j;
43     int temp;
44     for(i=1;i<=n;i++){
45         for(j=0;j<=suma-a[i];j++){
46             if(dp[i-1][j]==-1) continue;
47             temp=j+a[i];
48             if(dp[i][temp]==-1){
49                 dp[i][temp]=dp[i-1][j]+1;
50             }
51             else{
52                 dp[i][temp]=min(dp[i][temp],dp[i-1][j]+1);
53             }
54         }
55 
56         for(j=b[i];j<=suma;j++){
57             if(dp[i-1][j]==-1) continue;
58             temp=j-b[i];
59             if(dp[i][temp]==-1){
60                 dp[i][temp]=dp[i-1][j];
61             }
62             else{
63                 dp[i][temp]=min(dp[i][temp],dp[i-1][j]);
64             }
65         }
66     }
67 
68     for(j=0;j<=suma;j++){
69         if(dp[n][j]==-1) continue;
70         mi=min(mi,dp[n][j]);
71     }
72 }
73 
74 void out()
75 {
76     printf("%d\n",mi);
77 }
78 
79 int main()
80 {
81     //freopen("data.in","r",stdin);
82     scanf("%d",&T);
83     for(int cnt=1;cnt<=T;cnt++)
84     //while(T--)
85     //while(scanf("%d",&n)!=EOF)
86     {
87         ini();
88         solve();
89         out();
90     }
91 }

 

 

 

“亚信科技杯”南邮第七届大学生程序设计竞赛之网络预赛 (K L题解)

标签:

原文地址:http://www.cnblogs.com/njczy2010/p/4378596.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!