Bootstrap

Rock, Paper, Scissors(思维)

Rock, Paper, Scissors

题意:

两个人玩石头剪刀布游戏,第一个人可以出 a 1 a_1 a1个石头, a 2 a_2 a2个剪刀, a 3 a_3 a3个布;第二个人可以出 b 1 b_1 b1个石头, b 2 b_2 b2个剪刀, b 3 b_3 b3个布。其中, a 1 + a 2 + a 3 = b 1 + b 2 + b 3 = n a_1 + a_2 + a_3 = b_1 + b_2 + b_3 = n a1+a2+a3=b1+b2+b3=n。问第一个人最少赢多少次,最多赢多少次。

思路

最多赢多少次,比较容易想。这种情况就是自己每次出牌,对方都会出被自己克制的牌。那么赢的场次就是, a n s 1 = m i n ( a 1 , b 2 ) + m i n ( a 2 , b 3 ) + m i n ( a 3 , b 1 ) ans1 = min(a_1,b_2) + min(a_2,b_3) + min(a_3,b_1) ans1=min(a1,b2)+min(a2,b3)+min(a3,b1)
最少赢多少次,就是自己每次出牌,对方都会出克制自己的牌,或者打平的牌。但是如果直接这么去写的话,需要讨论很多情况,因此我们需要进一步思考。如果对方一直克制自己或者与自己打平的话,那么最后的时候会出现什么情况呢?就是最后自己剩下一种牌,若干张;对方也只剩下一种牌,若干张。并且自己的牌是克制对方的牌的。
以最后剩下石头和剪刀为例。因为我们分析的是最少赢多少次,那肯定在只剩下石头(剪刀)之前,可以尽可能地多消耗剪刀,这样可以使得最后赢的更少。那么我们可以干脆不看 b 1 b_1 b1 b 3 b_3 b3,直接消耗 b 2 b_2 b2。那么最后第二个人剪刀剩下的数量是 b 2 − a 2 − a 3 b_2 - a_2 - a_3 b2a2a3
如果只剩下剪刀(布)或者布(石头),同理可得。那么现在就得到了 3 3 3个数字,分别为 b 2 − a 2 − a 3 b_2 - a_2 - a_3 b2a2a3 b 1 − a 1 − a 2 b_1 - a_1 - a_2 b1a1a2 b 3 − a 1 − a 3 b_3 - a_1 - a_3 b3a1a3。但是这里会有一个问题,就是有可能这三个数是负数,那么就根本不会剩下了,那么最后分别只剩下一种牌,并且第一个人的克制第二个人的情况就不会出现了。如果是这样的话,那就最少赢 0 0 0次。最后的答案就是这三个数以及 0 0 0取最大值即可。
如果三个数中有多个正数,那么答案是多少呢?其实,这里有一个性质,那就是这三个数,最多只有一个正数。下面对这个结论做一个简单的证明。不妨设 b 2 − a 2 − a 3 > 0 b_2 - a_2 - a_3 > 0 b2a2a3>0,移项可得 b 2 > a 2 + a 3 b_2 > a_2 + a_3 b2>a2+a3,由于 a 1 + a 2 + a 3 = b 1 + b 2 + b 3 = n a_1 + a_2 + a_3 = b_1 + b_2 + b_3 = n a1+a2+a3=b1+b2+b3=n,则 a 1 > b 1 + b 3 a_1 > b_1 + b_3 a1>b1+b3,那么 b 1 − a 1 − a 2 < 0 , b 3 − a 1 − a 3 < 0 b_1 -a_1-a_2<0,b_3-a_1-a_3<0 b1a1a2<0,b3a1a3<0。证毕!

代码

#include <iostream>
#include <cstdio>

using namespace std;

int n;
int a[4], b[4];

int main()
{
	cin >> n;
	for(int i=1;i<=3;i++) cin >> a[i];
	for(int i=1;i<=3;i++) cin >> b[i];
	int ans1 = max(max(0, b[3]-a[3]-a[1]), max(b[2]-a[2]-a[3], b[1]-a[1]-a[2]));
	int ans2 = min(a[1],b[2]) + min(a[2],b[3]) + min(a[3],b[1]);
	cout << ans1 << ' ' << ans2 << endl;
	return 0;
}
;