hdu 计算机学院大学生程序设计竞赛(2015’11)

搬砖

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 5134    Accepted Submission(s): 1288


Problem Description
  小明现在是人见人爱,花见花开的高富帅,整天沉浸在美女环绕的笙歌妙舞当中。但是人们有所不知,春风得意的小明也曾有着一段艰苦的奋斗史。

  那时的小明还没剪去长发,没有信用卡没有她,没有24小时热水的家,可当初的小明是那么快乐,尽管甚至没有一把破木吉他…

  之所以快乐,是因为那时的小明心怀逆袭梦想。有一天,小明为了给他心目中的女神买生日礼物,来到了某建筑工地搬砖挣钱。就在这个时候,工地上又运来了一卡车的砖,包工头让小明把卡车卸下来的那堆砖分成一块一块的(要求任何2块转都要分开)。作为资深搬运工,小明总是每次将一堆砖分为两堆,这时候,所消耗的体力是分完之后两堆砖数目的差值。

  现在,已知卡车运来的砖的数目,请告诉小明最少要花费多少体力才能完成包工头所要求的任务呢?
Input
输入数据第一行是一个正整数T(T<=100),表示有T组测试数据。
接下来T行每行一个正整数N(N<=10000000),表示卡车运来的砖块的数目。
Output
对于每组数据,请输出小明完成任务所需的最少体力数。
Sample Input
2
4
5
Sample Output
0
2
 1 #include <cstdio>
 2 #include <queue>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <cstdlib>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <map>
 9 #include <set>
10 #include <ctime>
11 #include <cmath>
12 #include <cctype>
13 #define MAX 100000
14 using namespace std;
15 int T,n,a[2],num[2],sum;
16 int main()
17 {
18     //freopen("/home/user/桌面/in","r",stdin);
19     scanf("%d",&T);
20     while(T--)
21     {
22         scanf("%d",&n);
23         if(n==1)
24         {
25             puts("0");
26             continue;
27         }
28         sum=a[0]=a[1]=num[0]=num[1]=0;
29         if(n&1) a[1]=n,num[1]=1,a[0]=n-1,num[0]=0;
30         else a[0]=n,num[0]=1,a[1]=n+1,num[1]=0;
31         while(a[0]!=1)
32         {
33             //printf("%d %d %d %d
",a[0],a[1],num[0],num[1]);
34             if(a[0]&1) sum+=num[0];
35             if(a[1]&1) sum+=num[1];
36             if(a[0]&1)
37             {
38                 num[1]=(num[1]<<1)+num[0];
39             }    
40             else
41             {
42                 num[0]=(num[0]<<1)+num[1];
43             }    
44             a[0]>>=1;
45             a[1]=a[0]+1;
46         }
47         printf("%d
",sum);
48     }
49     //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
50     return 0;
51 }
View Code

投币洗衣机

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6165    Accepted Submission(s): 1585


Problem Description
  如今大学生的生活条件越来越好了,近期,内蒙某高校在每个寝室楼都添置了一台投币洗衣机。
  小明作为经常参加训练的ACM队员,非常忙(Lan)碌(Duo),当然非常乐意把衣服丢给洗衣机解决啦。根据要洗的衣服数量,投币洗衣机每次需要投入2-4 枚硬币。
  小明是一个非常容易出汗的男生,夏天就要到了,每天都要洗澡,所以也就有大量衣服需要洗。
  小明是这么制定投币洗衣机计划的:当屯积的衣服数量大于等于a且小于b的时候,他就会马上全部拿去给洗衣机洗,并且投入2枚硬币;当屯积的衣服数量大于等于b且小于c的时候,他就会马上全部拿去给洗衣机洗,并且投入3枚硬币;当屯积的衣服数量大于等于c的时候,他就会马上全部拿去给洗衣机洗,并且投入4枚硬币。其他细节见样例。

  现在知道,小明过去n 天每天换下的衣服数量v件,需要你帮忙计算出小明在过去这段时间洗衣服一共花了多少钱。
Input
输入包含多组测试数据。

每组数据第一行是4个正整数 n (1<=n<=10000) 、a 、b 、c (1<=a<b<c<=300),具体含义见题目描述。

每组数据第二行包含n个正整数,按顺序表示过去n天每天产生的衣服数量v(1<=v<=1000)。
Output
每组数据输出一个整数,表示小明过去n天中洗衣服一共花了多少钱。
每组输出占一行。
Sample Input
3 2 4 6
2 2 1
Sample Output
4
 
 1 #include <cstdio>
 2 #include <queue>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <cstdlib>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <map>
 9 #include <set>
10 #include <ctime>
11 #include <cmath>
12 #include <cctype>
13 #define MAX 100000
14 using namespace std;
15 int n,a,b,c,x,sum,money;
16 int main()
17 {
18     //freopen("/home/user/桌面/in","r",stdin);
19     while(scanf("%d%d%d%d",&n,&a,&b,&c)==4)
20     {
21         sum=money=0;
22         while(n--)
23         {
24             scanf("%d",&x);
25             sum+=x;
26             if(sum>=a&&sum<b)
27             {
28                 sum=0;
29                 money+=2;
30             }
31             else if(sum>=b&&sum<c)
32             {
33                 sum=0;
34                 money+=3;
35             }
36             else if(sum>=c)
37             {
38                 sum=0;
39                 money+=4;
40             }
41         }
42         printf("%d
",money);
43     }
44     //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
45     return 0;
46 }
View Code

玩骰子

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1219    Accepted Submission(s): 369

Problem Description

  Nias与Ains都特别喜欢玩骰子,而且都自以为比对方玩得更溜。
  终于有一天,他们决定用骰子来一决高下!
  一般的骰子玩法已经不足以体现他们的水平了,于是他们自创了一套玩法来PK:
首先,每人掷3个骰子;之后,可以选择其中一个骰子重新掷(当然也可以放弃这一步),最后,比较投掷结果的大小,结果大的那方获胜,一样的话为平局。
  大小比较规则为:
  三个一样数字的骰子称为三条;两个一样数字的骰子称为对子;只有一个数字的骰子成为散牌。三条>对子>散牌。当双方结果都为三条时,直接比较三条数字的大小;都有对子时,先比较对子数字的大小,若相同,再比较剩下的骰子的数字的大小;都只有散牌时,先比较最大的数字的大小,若相同,再比较次大的数字的大小,还相同,最后比较最小的数字的大小。

  现在Nias已经投了3个骰子,还剩一次机会可以选择其中一个骰子重新投(或不选),而且他已经知道了Ains的最后投掷结果,求Nias获胜的概率有多大。
Input
输入数据第一行为一个整数T,表示有T组测试数据。
接下来T行,每行6个1~6的整数,前三个表示Nias第一次的投掷结果,后三个表示Aias最终的投掷结果。 
Output
请输出Nias获胜的概率,结果保留3位小数,每组输出占一行。 
Sample Input
4
2 3 5 3 3 4
3 3 1 2 2 2
6 2 1 5 4 3
1 2 3 4 4 1
Sample Output
0.333
0.167
1.000
0.000
 1 #include <cstdio>
 2 #include <queue>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <cstdlib>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <map>
 9 #include <set>
10 #include <ctime>
11 #include <cmath>
12 #include <cctype>
13 #define MAX 100000
14 using namespace std;
15 int T,a[3],b[3];
16 int cmp(int*a,int*b)
17 {
18 //    printf("%d %d %d %d %d %d
",a[0],a[1],a[2],b[0],b[1],b[2]);
19     int c[7],d[7];
20     memset(c,0,sizeof(c));
21     memset(d,0,sizeof(d));
22     c[a[0]]++;c[a[1]]++;c[a[2]]++;
23     d[b[0]]++;d[b[1]]++;d[b[2]]++;
24     int m1=0,m2=0,i1,i2;
25     for(int i=1;i<=6;i++) m1=max(m1,c[i]);
26     for(int i=1;i<=6;i++) m2=max(m2,d[i]);
27 //    printf("%d %d
",m1,m2);
28     if(m1!=m2) return m1-m2;
29     for(i1=6;i1>0;i1--) if(c[i1]==m1) break;
30     for(i2=6;i2>0;i2--) if(d[i2]==m2) break;
31 //    printf("%d %d
",i1,i2);
32     if(i1!=i2||m1==3) return i1-i2;
33     c[i1]=d[i2]=0;
34     for(i1=6;i1>0;i1--) if(c[i1]) break;
35     for(i2=6;i2>0;i2--) if(d[i2]) break;
36 //    printf("%d %d
",i1,i2);
37     if(i1!=i2||m1==2) return i1-i2;
38     c[i1]=d[i2]=0;
39     for(i1=6;i1>0;i1--) if(c[i1]) break;
40     for(i2=6;i2>0;i2--) if(d[i2]) break;
41 //    printf("%d %d
",i1,i2);
42     return i1-i2;
43 }
44 int main()
45 {
46     //freopen("/home/user/桌面/in","r",stdin);
47     scanf("%d",&T);
48     while(T--)
49     {
50         scanf("%d%d%d",&a[0],&a[1],&a[2]);
51         scanf("%d%d%d",&b[0],&b[1],&b[2]);
52         if(cmp(a,b)>0)
53         {
54             printf("%.3lf
",1.0);
55             continue;
56         }
57         int c,maxc=0,a1[3];
58         for(int i=0;i<3;i++)
59         {
60             memcpy(a1,a,sizeof(a));
61             c=0;
62             for(int j=1;j<=6;j++)
63             {
64                 a1[i]=j;
65                 if(cmp(a1,b)>0) c++;
66             }
67 //            printf("%d
",c);
68             maxc=max(c,maxc);
69         }
70         printf("%.3lf
",maxc/6.0);
71     }
72     //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
73     return 0;
74 }
View Code

质方数

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3655    Accepted Submission(s): 1228

Problem Description

  小明天生对数字比较敏感,3岁的时候就能背诵圆周率一百位。

  现在,小明慢慢长大了,但依然很喜欢数字,最近,他迷上了质数和平方数,并且自己把质数的平方命名为“质方数”。
  现在,他在研究这样一个问题:距离一个正整数N最接近的质方数是多少?
Input
输入数据第一行是一个正整数T(T<=20),表示有T组输入数据。
接下来T行,每行输入一个正整数N(1<=N<=10^8)。
Output
对于每组数据,请输出距离N最接近的质方数,每组输出占一行。
Sample Input
2
1
10 
Sample Output
4
9
 1 #include <cstdio>
 2 #include <queue>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <cstdlib>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <map>
 9 #include <set>
10 #include <ctime>
11 #include <cmath>
12 #include <cctype>
13 #define MAX 11000
14 using namespace std;
15 int T,n,zfs[MAX+10],zn,notpri[MAX];
16 void init()
17 {
18     memset(notpri,0,sizeof(notpri));
19     zfs[0]=-MAX;
20     zn=1;
21     for(int i=2;i<=MAX;i++)
22         if(!notpri[i]) for(int j=i*i;j<=MAX;j+=i) notpri[j]=1;
23     for(int i=2;i<=MAX;i++) if(!notpri[i]) zfs[zn++]=i*i;
24 }
25 int main()
26 {
27     //freopen("/home/user/桌面/in","r",stdin);
28     init();
29     scanf("%d",&T);
30     while(T--)
31     {
32         scanf("%d",&n);
33         int *a=lower_bound(zfs,zfs+zn,n);
34         printf("%d
",*a-n>n-*(a-1)?*(a-1):*a);
35     }
36     //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
37     return 0;
38 }
View Code

ACM组队安排

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1051    Accepted Submission(s): 512

Problem Description
  ACM亚洲区比赛结束,意味着开始备战明年的浙江省大学生程序设计竞赛了!
  杭州电子科技大学ACM集训队也准备开始组队。
  教练想把所有的n个队员组成若干支队伍,原则是每支队伍至少一人,最多三人。
  现在问题来了:如果已知集训队队员的数量n,请你帮教练计算出所有可能的组队方案有多少种。
  特别说明:
  队伍没有编号,即如果有A,B,C三人,{A}{BC}与{BC}{A}是同一种组队情况。
Input
输入包含多组测试数据(约1000组),每组数据占一行,包含一个数字n(0<=n<=20),表示ACM集训队的队员人数;n为0,表示输入结束。
Output
请输出n个队员所有可能的组队方案数,每组输出占一行。
Sample Input
1 2 3 4 5 0
Sample Output
1 2 5 14 46
 1 #include <cstdio>
 2 #include <queue>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <cstdlib>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <map>
 9 #include <set>
10 #include <ctime>
11 #include <cmath>
12 #include <cctype>
13 #define MAX 100000
14 using namespace std;
15 long long d[4][21],c[21][4];
16 int n;
17 long long A(int m,int n)
18 {
19     long long ans=1;
20     for(;n>0;n--,m--) ans*=m;
21     return ans;
22 }
23 long long C(int m,int n)
24 {
25     return A(m,n)/A(n,n);
26 }
27 void init()
28 {
29     memset(d,0,sizeof(d));
30     for(int i=0;i<=20;i+=3)
31     {
32         d[3][i]=A(i,i)/A(i/3,i/3);
33         for(int j=0;j<i;j+=3) d[3][i]/=A(3,3);
34 //        printf("%lld %lld %lld %lld
",A(i,i),i/3*A(3,3),A(i/3,i/3),d[3][i]);
35     }
36 //    for(int i=0;i<=20;i++) printf("%lld ",d[3][i]);printf("
");
37     for(int i=0;i<=20;i++)
38     {
39         long long t;
40         for(int j=0;j<=i;j+=2)
41         {
42             t=A(i,j)/A(j/2,j/2);
43             for(int k=0;k<j;k+=2) t/=A(2,2);
44             d[2][i]+=t*d[3][i-j];
45         }
46     }
47 //    for(int i=0;i<=20;i++) printf("%lld ",d[2][i]);printf("
");
48     for(int i=0;i<=20;i++)
49     {
50         long long t;
51         for(int j=i;j>=0;j--)
52         {
53             t=A(i,j)/A(j,j);
54             d[1][i]+=t*d[2][i-j];
55         }
56     }
57 //    for(int i=0;i<=20;i++) printf("%lld ",d[1][i]);printf("
");
58 }
59 int main()
60 {
61     //freopen("/home/user/桌面/in","r",stdin);
62     init();
63     while(scanf("%d",&n)==1&&n) printf("%lld
",d[1][n]);
64     //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
65     return 0;
66 }
View Code

逆袭指数

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1868    Accepted Submission(s): 379

Problem Description
  这依然是关于高富帅小明曾经的故事——

  尽管身处逆境,但小明一直没有放弃努力,除了搬砖,小明还研究过东方的八卦以及西方的星座,一直试图在命理上找到自己能够逆袭的依据。

  当这些都失败以后,小明转向了数学研究,希望从中得到一些信息。一天,小明在研究《BestCoder逆袭的数理基础》这本书时,发现了宝贵的信息,其中写道:
  每个人都存在一个逆袭指数,对于这个逆袭指数,可能存在连续的因子,如果这个连续因子足够长的话,那么这个人逆袭的概率就很大!

  小明已知自己的逆袭指数,请告诉小明他最长的连续因子,以让他来判断他自己是否能够逆袭。
Input
输入包含多组测试数据。
每组数据占一行,包含一个整数N,表示小明的逆袭指数,N小于2^31。
Output
对于每组数据,请输出2行:
第一行输出最长的因子个数;
第二行输出最小的因子序列,具体请参考样例.
特别说明:由于小明十分讨厌单身,所以1不算因子。
Sample Input
630
12
 
Sample Output
3
5*6*7
2
2*3
Hint
630 = 3*5*6*7
 
 1 #include <cstdio>
 2 #include <queue>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <cstdlib>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <map>
 9 #include <set>
10 #include <ctime>
11 #include <cmath>
12 #include <cctype>
13 #define MAX 0x7fffffff
14 using namespace std;
15 long long a[13][2000],a2[50000];
16 int n,an[14];
17 int main()
18 {
19     //freopen("/home/user/桌面/in","r",stdin);
20     a2[3]=6;
21     for(an[2]=4;a2[an[2]-1]<=MAX;an[2]++) a2[an[2]]=a2[an[2]-1]/(an[2]-2)*an[2];
22     an[2]--;
23 //        printf("%d %d
",a2[an[2]],a[2][an[2]-1]);
24     //for(int i=3;i<100;i++) printf("%lld ",a2[i]);printf("
");
25     for(int i=3,j;i<=12;i++)
26     {
27         a[i][1]=1;
28         for(j=2;j<i+2;j++) a[i][j]=j*a[i][j-1];
29         //printf("%d
",(int)a[i][j-1]);
30         for(;a[i][j-1]<=MAX;j++) a[i][j]=a[i][j-1]/(j-i)*j;
31         an[i]=j-1;
32 //        printf("%d %d
",a[i][an[i]],a[i][an[i]-1]);
33         //printf("%d
",an[i]);
34         //for(int k=i+1;k<an[i];k++) printf(" %lld",a[i][k]);printf("
");
35     }
36     while(scanf("%d",&n)==1)
37     {
38         if(n==1)
39         {
40             printf("0

");
41             continue;
42         }
43         if(n==0)
44         {
45             printf("1
0
");
46             continue;
47         }
48         int find=0;
49         for(int i=12,j;i>2;i--)
50         {
51             for(j=i+1;j<an[i]&&n>=a[i][j];j++)
52             {
53                 if(n%a[i][j]==0)
54                 {
55                     find=1;
56                     break;
57                 }
58             }
59             if(find)
60             {
61                 printf("%d
%d",i,j-i+1);
62                 for(int k=j-i+2;k<=j;k++) printf("*%d",k);
63                 printf("
");
64                 break;
65             }
66         }
67         if(find) continue;
68         int i;
69         for(i=3;i<an[2]&&n>=a2[i];i++)
70         {
71             if(n%a2[i]==0)
72             {
73                 find=1;
74                 break;
75             }
76         }
77         if(find)
78         {
79             printf("2
%d*%d
",i-1,i);
80             continue;
81         }
82         int m=sqrt(n);
83         for(i=2;i<=m;i++)
84             if(n%i==0)
85             {
86                 find=1;break;
87             }
88         printf("1
%d
",find?i:n);
89     }
90     //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
91     return 0;
92 }
View Code

油菜花王国

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2254    Accepted Submission(s): 581

Problem Description
  程序设计竞赛即将到来,作为学校ACM集训队主力,小明训练一直很努力。今天天气不错,教练也心情大好,破例给各位队员放假一天,小明就骑着自己的小电驴到郊外踏青去了。

  出城不久,小明看到一大片油菜花,忍不住眼前美景的诱惑,就拐了进去,谁曾想,这一拐却误入了油菜花王国!

  油菜花王国生存着一大批油菜花精灵,这是一种特别热爱斐波那契数列的生物。在这个国度里,有若干个家族,每只精灵都只属于一个家族。精灵出生时,身上都会印着一个编码,表示这只精灵的能力值,如果这个能力值正好存在于斐波那契数列,那么他就会为所在的家族增加一点威望。小明通过和精灵们聊天,知道了所有精灵之间的关系。

  现在,小明想知道油菜花王国里威望值最大的家族的威望值是多少,你能帮帮他吗?小明会把精灵们之间的关系网络告诉你,由于整个关系网络实在太庞大,所以小明很有可能重复介绍其中一些关系。
Input
输入包含多组数据。
每组数据第一行包含两个整数 n (1 <= n <= 1000) 、 m (1 <= m <= 5000) ,分别表示油菜花王国精灵数量和精灵之间关系组数。
第二行包含 n 个整数,表示精灵们的能力值 k (1 <= k <= 1000000000)。
接下去有 m 行,每行有两个不同的整数 u 、 v (1 <= u, v <= n) ,表示精灵 u 和精灵 v 属于同一个家族。
Output
请输出威望值最大的家族的威望值,每组数据对应一行输出。
Sample Input
2 1
1 4
1 2
Sample Output
1
 1 #include <cstdio>
 2 #include <queue>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <cstdlib>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <map>
 9 #include <set>
10 #include <ctime>
11 #include <cmath>
12 #include <cctype>
13 #define MAX 1000000000
14 using namespace std;
15 int n,m,ss[1010],sum[1010];//n num of v,m num of edge
16 bool v[1010];
17 set<int>fib;
18 void init()
19 {
20     fib.clear();
21     int a0,a1,a2;
22     fib.insert(1);
23     a1=1;a2=2;
24     while(a2<=MAX)
25     {
26         fib.insert(a2);
27         a2=a1+a2;
28         a1=a2-a1;
29     }
30 }
31 int findset(int x)
32 {
33     return ss[x]!=x?ss[x]=findset(ss[x]):x;
34 }
35 int findset1(int x)
36 {
37     int stacks[1010],i=-1;
38     while(ss[x]!=x)
39     {
40         stacks[++i]=x;
41         x=ss[x];
42     }
43     while(i>=0)
44     {
45         ss[stacks[i]]=x;
46         i--;
47     }
48     return x;
49 }
50 int main()
51 {
52     //freopen("/home/user/桌面/in","r",stdin);
53     init();
54     //for(set<int>::iterator i=fib.begin();i!=fib.end();i++) printf("%d ",*i);printf("
");
55     while(scanf("%d%d",&n,&m)==2)
56     {
57         for(int i=1,a;i<=n;i++)
58         {
59             scanf("%d",&a);
60             fib.count(a)?v[i]=1:v[i]=0;
61         }
62         for(int i=1;i<=n;i++) ss[i]=i;
63         for(int a,b,i=0;i<m;i++)
64         {
65             scanf("%d%d",&a,&b);
66             int x,y;
67             x=findset(a);y=findset(b);
68             ss[x]=y;
69         }
70         memset(sum,0,sizeof(sum));
71         int maxsum=-1;
72         for(int i=1;i<=n;i++)
73         {
74             int idx=findset(i);
75             sum[idx]+=v[i];
76         }
77         for(int i=1;i<=n;i++) 
78             maxsum=max(maxsum,sum[i]);
79         printf("%d
",maxsum);
80     }
81     //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
82     return 0;
83 }
View Code

游乐场

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5362    Accepted Submission(s): 857

Problem Description
  小时候,因为家里经济困难,小明从未去过游乐场,所以直到现在,他还心存遗憾。
  最近,杭州刚建了一座游乐场,为了弥补儿时的遗憾,小明带了一笔钱迫不及待地要去体验一番。
  由于是第一次来到这种地方,小明也不知哪些项目比较好玩,因此他想体验尽可能多的项目。来之前,小明还向朋友打听了一下关于游乐场的情况,只要是朋友推荐过的,他一定要体验。当然,每个项目都需要一定的花费,当小明的钱不够时就不能再玩了。

  现在,已知小明身上的钱以及每个游戏项目的花费,请问小明最多能体验多少个项目?
Input
输入第一行为一个整数T,表示有T组测试数据。

对于每组数据:
第一行是三个整数n, m, k,分别表示游乐场里的游戏项目数,朋友推荐的游戏项目数,小明身上的钱数(1<=m<=n<=10000, 1<=k<=10^9)。
第二行是n个整数,第i个整数xi表示第i个游戏项目的费用(1<=xi<=10^9)。
第三行是m个整数pi,表示朋友推荐第pi个游戏项目(1<=pi<=n)。
Output
如果小明带的钱连朋友推荐的项目都无法全部体验,请输出-1;否则,请输出小明最多能体验的项目数。
每组输出占一行。
Sample Input
2
5 2 10
4 3 8 1 12
1 2
5 2 10
4 3 8 1 12
1 3
Sample Output
3
-1 
 1 #include <cstdio>
 2 #include <queue>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <cstdlib>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <map>
 9 #include <set>
10 #include <ctime>
11 #include <cmath>
12 #include <cctype>
13 #define MAX 10000
14 using namespace std;
15 int T,n,m,k,costs[MAX+10],cost[MAX+10],costidx[MAX+10],idx[MAX+10],vis[MAX+10];
16 bool com(int&a,int&b)
17 {
18     return cost[a]<cost[b];
19 }
20 int main()
21 {
22     //freopen("/home/user/桌面/in","r",stdin);
23     scanf("%d",&T);
24     while(T--)
25     {
26         scanf("%d%d%d",&n,&m,&k);
27         memset(vis,0,sizeof(vis));
28         for(int i=1;i<=n;i++) scanf("%d",&costs[i]);
29         for(int i=0;i<m;i++)
30         {
31             scanf("%d",&idx[i]);
32             vis[idx[i]]=1;
33             costidx[i]=costs[idx[i]];
34         }
35         int j=0;
36         for(int i=1;i<=n;i++) if(!vis[i]) cost[j++]=costs[i];
37         sort(costidx,costidx+m);
38         sort(cost,cost+j);
39         int i,sum=0;
40         for(i=0;i<m;i++)
41         {
42             sum+=costidx[i];
43             if(sum>k) break;
44         }
45         if(i<m)
46         {
47             puts("-1");
48             continue;
49         }
50         n=j;
51         for(int j=0;j<n;j++)
52         {
53             sum+=cost[j];
54             if(sum>k) break;
55             i++;
56         }
57         printf("%d
",i);
58     }
59     //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
60     return 0;
61 }
View Code
原文地址:https://www.cnblogs.com/cdyboke/p/5057057.html