训练赛第二场G题 ZOJ 2343

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2343

解题报告:首先我假设最后的正确的结果是a[1] , a[2] ,a[3] ....a[i];然后我们先把这M个金币完全按照x[i] / Y的比例先预分配一下,分配的同时,统计出分配结束后还会剩余多少个金币,假设第一轮分配之后每个人得到的金币数量分别是k[1],k[2],......k[i],那么可以确定的是

a[i] - k[i] 是等于0或者等于1的,也就是说如果有些人的当前拿到的金币数量并不是符合最后的结果的话,那么这个人当前拿到的金币最多只比他应该得到的金币的数量少了一个,于是我们现在就可以将剩余的这left个金币分配给所有还少拿了一个金币的人,那么到底应该分给谁呢?

很显然,应该分给那个x[i]/Y - k[i]/M最大 的人,因为当分给这个人之后这个人的x[i]/Y - k[i]/M的值一定会变小,这样就可以达到总的值最小的目的。

 1 #include<cstdio>
 2 double Y,x[1005];
 3 int N,M,k[1005];
 4 
 5 int main()
 6 {
 7     int T;
 8     scanf("%d",&T);
 9     while(T--)
10     {
11         scanf("%d%d%lf",&N,&M,&Y);
12         for(int i = 0;i < N ;++i)
13         scanf("%lf",&x[i]);
14         int left = M;
15         for(int i = 0;i<N;++i)
16         {
17             k[i] = 1.0 * ( x[i] / Y ) * M;
18             left -= k[i];
19         }
20         while(left)
21         {
22             int l = 0;
23             for(int i = 0 ;i < N;++i)
24             if(1.0*(double)x[i]/Y-(double)k[i]/(double)M >= 1.0*(double)x[l]/Y-(double)k[l]/(double)M)
25             l = i;
26             k[l]++;
27             left--;
28         }
29         for(int i = 0;i < N;++i)
30         printf(i == 0? "%d":" %d",k[i]);
31         puts("");
32     }
33     return 0;
34 }
35         
36         
View Code
原文地址:https://www.cnblogs.com/xiaxiaosheng/p/3304358.html