【ZOJ - 2968 】Difference Game (贪心,思维模拟)
題干:
Now you are going to play an interesting game. In this game, you are given two groups of distinct integers and?C?coins. The two groups, named?Ga?and?Gbrespectively, are not empty and contain the same number of integers at first. Each time you can move one integer in one group to the other group. But a move that makes a group empty is considered as invalid. Each move will cost you?p?coins, and?pequals the difference of the size between the two group (take the absolute value. e.g. moving a number from the group of size 4 to the group of size 6 will cost you |4 - 6| = 2 coins, and moving a number between two group with same size will not cost any coins). You can do as many moves as you wish, so long as the total cost does not exceed?C.
Let?M?be the minimum integer in?Ga, and?N?be the maximum integer in?Gb. The purpose of this game is to produce a maximum (M?-?N).
Input
Standard input will contain multiple test cases. The first line of the input is a single integer?T?(1 <=?T?<= 60) which is the number of test cases. And it will be followed by?T?consecutive test cases.
Each case begin with two integers?S?(1 <=?S?<= 20000, indicating the size of?Ga?and?Gb?at first) and?C?(0 <=?C?<= 1000000). Two lines of?S?integers follow, representing the numbers in?Ga?and?Gb?respectively. All these integers are distinct and are between 1 and 50000, both inclusive.
Output
Results should be directed to standard output. The output of each test case should be a single integer in one line, which is the maximum possible value for?M?-?N?after some moves.
Sample Input
?
2 1 10 10 12 2 10 1 2 3 4?
Sample Output
?
-2 1?
Hint
For Sample 1, two groups are of size 1, so no moves can be done because any moving will make Ga or Gb empty, which is not valid. So M = 10, N = 12, M - N = -2.
For Sample 2, one valid steps of moves is:
Move 1 in Ga to Gb, cost 0 coins.
Move 3 in Gb to Ga, cost 2 coins.
Move 4 in Gb to Ga, cost 0 coins.
Then Ga contains 2 3 4, Gb contains 1, M = 2, N = 1, M - N = 1. This is the maximum possible value.
題目大意:
有Ga、Gb兩堆數字,初始時兩堆數量相同。從一堆中移一個數字到另一堆的花費定義為兩堆之間數
量差的絕對值,初始時共有錢C。求移動后Ga的最小值減Gb的最大值可能的最大值。
解題報告:(鏈接)
假如有足夠錢移動,那么Ga的最大值和Gb的最小值應該是兩堆合并后排序中相鄰的兩數。那么我們 就枚舉這個數。
枚舉的時候我們需要確定形成這個情況(大的都在Ga堆,小的都在Gb堆)的最少花費,這個花費可以這樣解決,假設Ga中向Gb中需要移入ab個數,Gb需要向Ga移入ba個數,首先當然是Ga移一個給Gb,然后Gb移一個給Ga,這樣直到某一一堆需要移出都移出停止,此時的花費就是 2*min(ab,ba)。接著就是其中一堆一直移給另一堆,每移一次費用用會增2,所以此時的花費為 |ab-ba|*(|ab-ba|-1)。總花費就為2*min(ab,ba) + |ab - ba| *(|ab -ba|- 1)。 當然可能沒有足夠錢移動,Ga堆的最小值永遠小于Gb堆的最大值,這樣我們當然要把Ga堆前C/2 (C/2+1)小的移到Gb堆,Gb堆前C/2+1(C/2)的移到Ga堆,當然是交替移。
但是做完題后,有個疑問,如果A中的值很大,B中的值很小,那是不是選擇不移動,會得到更優答案?
答案是否定的,(也就是說首先拿到這題第一顆定心丸就是:交換總比不交換要好,也就是如果還有錢就一定要去交換),因為他是要?,所以你把Bmax或者Amin換過去,會使得Amin變大,Bmax變小,所以對兩個參數都有利,那么根據貪心原則,何樂而不為?
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair using namespace std; const int MAX = 4e5 + 5; int n; struct Node {ll val;int id;bool operator<(const Node & b) {return val < b.val;} } g[MAX],ga[MAX],gb[MAX]; int suma[MAX],Sumb[MAX]; int main() {int t;cin>>t;int s,c;while(t--) {memset(g,0,sizeof g);memset(ga,0,sizeof ga);memset(gb,0,sizeof gb);memset(suma,0,sizeof suma);memset(Sumb,0,sizeof Sumb);scanf("%d%d",&s,&c);ll ans = -1;for(int i = 1; i<=s; i++) scanf("%lld",&ga[i].val),ga[i].id = 1;for(int i = 1; i<=s; i++) scanf("%lld",&gb[i].val),gb[i].id = 2;for(int i = 1; i<=2*s; i++) {if(i<=s) g[i] = ga[i];else g[i] = gb[i-s];}sort(ga+1,ga+s+1);sort(gb+1,gb+s+1);sort(g+1,g+2*s+1);for(int i = 1; i<=2*s; i++) {suma[i] = suma[i-1];if(g[i].id == 1) suma[i]++;}for(int i = 2*s; i>=1; i--) {Sumb[i] = Sumb[i+1];if(g[i].id == 2) Sumb[i]++;}if(s == 1) {printf("%d\n",ga[1].val-gb[1].val);continue;}for(int i = 1; i<2*s; i++) {//在i這個地方斷開int numa = suma[i];int numb = Sumb[i+1];int ci = min(numa,numb);ll tmp;//花錢數if(ci == numa) {ll sheng = numb - numa;tmp = ci*2 + sheng*(sheng-1);} else {ll sheng = numa - numb;tmp = ci*2 + sheng*(sheng-1);}if(tmp <= c) {ans = max(ans,g[i+1].val-g[i].val);}}if(ans==-1) {int ci = c/2+1;ans=max(ga[ci].val-gb[s-ci].val,ga[ci+1].val-gb[s-(ci-1)].val);}printf("%lld\n",ans);}return 0 ; }?
總結
以上是生活随笔為你收集整理的【ZOJ - 2968 】Difference Game (贪心,思维模拟)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 办信用卡前期费用 正规途径办卡不收费
- 下一篇: 【HDU - 5777】domino(贪