【博弈】2012 world final L.Takeover Wars
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=547&page=show_problem&problem=4048
又是我最喜欢的博弈,感觉非常难。。但是最后还是给我切掉了^_^!
两个集团在进行收购战争,每次每个集团可以采用两种收购操作,
1.用自己的子公司a收购自己另外的子公司b,完成之后b公司消失,a公司价值变成val[a]+val[b],
2.用自己的子公司a收购对方的子公司c,必须满足val[a]>val[c],完成之后c公司小时,a公司价值不变
双方轮流操作,直到某一方没有子公司存在则输。
详细证明我画了几张a4纸,就不搬上来,讲一下几个关键的结论,及其推导方向。
1.集团内部的收购必然是最大的子公司与次大的子公司之间进行。显然这样具备其他两个子公司合并所能拥有的所有好处。
2.集团间的收购,必然是针对对方最大的子公司。直观上可以这样想,如果你可以收购对方最大公司,你不可能去收购对方其他的公司;否则,你收购完了对方的b公司,对方将收购掉你当前最大子公司a。。由于val[a]>val[b],这样的交换对你是不利的。。当然很容易举出交换之后你还可以获胜的反例,但是可以证明这些例子执行合并操作也将获胜,故排除掉收购对方最大子公司之外的恶意收购。
3.某个集团开始内部合并的时候,另外的集团也只能执行内部合并,直到某个集团新合并出来的最大的子公司,已经比对方当前最大的子公司小,此时胜负已经分晓,因为对方可以不停收购掉你新合并出来的公司,而使得你永远无法消灭他当前最大的子公司。。这个的证明必需依赖于2,当对方执行操作1之后,对于我方只有两种可能A可以收购对面新合并出来的子公司,此时获胜游戏结束,B不能,故由2可以得知此时我方也只能执行内部收购。
有了这3点就可以很快解决问题了,此时可以将分成两种情况A.第一个集团一开始就先执行内部收购;B.第一个集团先执行恶意收购。之后根据1,2,3,有无论哪种情况第二个集团只能执行内部收购,直到胜负分晓。。。故整个题目只有一次决策,总复杂度为排序+O(n);
//By Lin #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<set> #include<vector> #include<map> #include<queue> #define sqr(x) ((x)*(x)) #define Rep(i,n) for(int i = 0; i<n; i++) #define foreach(i,n) for( __typeof(n.begin()) i = n.begin(); i!=n.end(); i++) #define X first #define Y second #define mp(x,y) make_pair(x,y) using namespace std; typedef long long LL; typedef pair<int,int> pii; #define N 100010 LL data[2][N]; int n[2]; bool solve(){ LL a = data[0][0], b = data[1][0]; for(int i = 1; i<=max(n[0],n[1]); i++){ a += data[0][i]; if ( a < b ) break; b += data[1][i]; if ( a > b ) return true; } if ( data[0][0] < data[1][0] ) return false; a = data[0][0], b = data[1][1]; for(int i = 2; i<=max(n[0],n[1]); i++){ b += data[1][i]; if ( b < a ) return true; a += data[0][i-1]; if ( a < b ) return false; } return false; } int main(){ int tt = 0; while ( ~scanf("%d%d", &n[0], &n[1] ) ){ memset( data , 0 , sizeof(data) ); Rep(k,2) { Rep(i,n[k]) scanf("%lld", &data[k][i] ); sort( data[k] , data[k]+n[k] ); reverse( data[k] , data[k]+n[k] ); } printf("Case %d: %s\n" , ++tt , solve()?"Takeover Incorporated":"Buyout Limited" ); } return 0; }