杭电多校七 1008-Triangle Game(博弈)

题目链接:杭电多校7 - Virtual Judge

样例输入: 

3
2 2 3
2 3 4
5 3 4

样例输出:

Win
Lose
Win

题意:一开始给定一个非退化三角形的三边长a,b,c,两个人轮流操作,,每次操作可以选择一个边长将其减少不小于1个单位长度,要保证操作后必须还是非退化三角形,保证两个玩家都是采取的最优策略,问先手是必胜还是必败。

注意下面以^代表异或

分析:结论:先手胜当且仅当(a-1)^(b-1)^(c-1)!=0。

我们定义先手的必胜态为W态:(a-1)^(b-1)^(c-1)!=0

必败态为L态:(a-1)^(b-1)^(c-1)==0

我们先来看一下必败态是不是一个非退化三角形,假设a<=b<=c,c-1=(a-1)^(b-1)<=(a-1)+(b-1)等价于c<a+b,所以显然必败态是一个非退化三角形。

根据博弈论的知识我们知道,一个必胜态一定能够经过一次操作到达必败态,而一个必败态无论怎样操作都只能到达必胜态。

下面我们分别来证明这两个结论:
假设我们当前处于必败态L态,也就是有(a-1)^(b-1)^(c-1)==0

假设a<=b<=c

如果a等于1,那么代入必败态条件种可以知道有b==c,那么这显然是一个必败态,也就是说先手已经无法操作。

如果a不等于1,那么肯定有b<c,那么就有1<a<b<c,那么显然我们可以对a,b,c中的一个数进行操作,不妨假设对a进行操作,得到x,那么有a>x,由于(b-1)^(c-1)=a-1>x-1,那么显然有(b-1)^(c-1)^(x-1)!=0,也就是说我们由必败态走到了必胜态,而且无论如何都无法找到一个x使得(b-1)^(c-1)^(x-1)==0,也就是说我们由必败态只能走到必胜态。

下面我们证一下由必胜态存在一种合法方案走到必败态。

这里的证明方法类似于尼姆博弈:我们令x=(a-1)^(b-1)^(c-1),那么如果我把(a-1)或者(b-1)或者(c-1)的其中一个对应地换成(a-1)^x,(b-1)^x,(c-1)^x,那么就会得到操作后的三个数异或值变为0.能这样进行操作的条件就是(a-1)>(a-1)^x,(b-1)>(b-1)^x,(c-1)>(c-1)^x三个不等式中至少有一个是成立的,由于x=(a-1)^(b-1)^(c-1),那么x的二进制中为1的位置代表在(a-1)、(b-1)、(c-1)这三个数中的出现次数为奇数次,那么我们不妨让x中最高位为1的那一位上也为1的一个数来跟x进行异或,那么异或后值肯定会变小,那么也就是说三个不等式中肯定有成立的不等式,所以也就是说一定存在一个操作使得我们从必胜态走到必败态。

证毕!

下面是代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		if(((a-1)^(b-1)^(c-1))!=0) printf("Win\n");
		else printf("Lose\n");
	}
	return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 根据三角形不等式,我们可以编写一段C语言代码来判断三条线段的长度能否组成三角形,如果不能,则输出No,如果能,请判断此三角形是否为等边三角形,若是则输出E-Triangle,否则输出G-Triangle。以下是编写的C语言程序:#include<stdio.h> int main() { int a,b,c; scanf("%d %d %d",&a,&b,&c); if(a+b>c && a+c>b && b+c>a) { if(a==b && a==c) printf("E-Triangle"); else printf("G-Triangle"); } else printf("No"); return 0; } ### 回答2: 可以通过以下步骤来判断三条线段能否组成三角形,并判断是否为等边三角形: 1. 首先,输入三个整数表示三条线段的长度,分别为a、b和c。 2. 判断三个数是否大于0,若有任一条线段长度小于等于0,则输出"No"。 3. 判断是否满足三角形的三边关系,即任意两边之和大于第三边。若不满足该条件,则输出"No"。 4. 判断是否为等边三角形,若三个数都相等,则输出"E-Triangle";否则,输出"G-Triangle"。 以下是对应的C语言代码实现: ```c #include<stdio.h> int main() { int a, b, c; // 输入三个整数 printf("请输入三个整数,分别表示三条线段的长度:\n"); scanf("%d%d%d", &a, &b, &c); // 判断三角形是否合法 if (a <= 0 || b <= 0 || c <= 0 || (a+b <= c) || (a+c <= b) || (b+c <= a)) { printf("No\n"); } else { // 判断是否为等边三角形 if (a == b && b == c) { printf("E-Triangle\n"); } else { printf("G-Triangle\n"); } } return 0; } ``` 该程序首先通过`scanf`函数输入三个整数,判断是否满足三角形的三边关系,并判断是否为等边三角形,并输出相应结果。 ### 回答3: 可以根据三角形的性质来判断三条线段能否组成一个三角形。三角形的任意两边之和大于第三边,任意两边之差小于第三边。所以我们可以编写一个判断三角形的函数。再判断是否为等边三角形。 首先,定义一个函数isTriangle(int a, int b, int c),用于判断三条边a、b、c能否组成一个三角形: ```c int isTriangle(int a, int b, int c) { if (a + b > c && a + c > b && b + c > a) { return 1; } else { return 0; } } ``` 再定义一个函数isEquilateral(int a, int b, int c),用于判断三角形是否为等边三角形: ```c int isEquilateral(int a, int b, int c) { if (a == b && b == c) { return 1; } else { return 0; } } ``` 在主函数中,读入三个整数表示三条线段的长度,调用isTriangle函数判断是否为三角形,如果不是则输出"No",否则调用isEquilateral函数判断是否为等边三角形,如果是则输出"E-Triangle",否则输出"G-Triangle"。 ```c #include <stdio.h> int isTriangle(int a, int b, int c) { if (a + b > c && a + c > b && b + c > a) { return 1; } else { return 0; } } int isEquilateral(int a, int b, int c) { if (a == b && b == c) { return 1; } else { return 0; } } int main() { int a, b, c; printf("请输入三条线段的长度:"); scanf("%d %d %d", &a, &b, &c); if (!isTriangle(a, b, c)) { printf("No\n"); } else if (isEquilateral(a, b, c)) { printf("E-Triangle\n"); } else { printf("G-Triangle\n"); } return 0; } ``` 以上就是判断三条线段是否能组成三角形以及是否为等边三角形的C语言程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值