UVA 11249 - Game(博弈)

UVA 11249 - Game

题目链接

题意:两堆石头,a和b,每次能取一堆任意数量,或者两堆同时取,但是绝对值差不能超过k,最后不能取的人输,问先手是否能赢

思路:先假设(a, b)石子,a是少的一堆,首先很容易看出(1, k + 2)是必败的,设下一个是(2, x)那么如果这个状态能到(1, k + 2)那么就是必胜,要找出(2, x)必败状态,就必然是上个状态多的一堆石子 + k + 2 - 1,这样无论怎么取,都无法变成(1, k + 2),而后手由于先手取掉了一个,就可以了,因此可以这样一个个去预处理出10W的必败状态,然后每次询问直接判断即可

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 100005;

int t, k, q, a, b;
int lose[N];

void init(int k) {
    memset(lose, 0, sizeof(lose));
    lose[1] = 1 + k + 1;
    lose[1 + k + 1] = 1;
    int pre = 1;
    for (int i = 2; i <= 100000; i++) {
	if (lose[i]) continue;
	int tmp = lose[pre] + i - pre + k + 1;
	if (tmp > 100000) break;
	pre = i;
	lose[i] = tmp;
	lose[tmp] = i;
    }
}

int main() {
    scanf("%d", &t);
    while (t--) {
	scanf("%d%d", &k, &q);
	init(k);
	while (q--) {
	    scanf("%d%d", &a, &b);
	    if (a > b) swap(a, b);
	    if (lose[a] == b) printf("LOSING\n");
	    else printf("WINNING\n");
	}
	printf("\n");
    }
    return 0;
}

UVA 11249 - Game(博弈),布布扣,bubuko.com

时间: 2024-08-01 21:20:49

UVA 11249 - Game(博弈)的相关文章

uva 11249 - Game(组合游戏)

题目链接:uva 11249 - Game 题目大意:给定K和N,表示有N轮游戏,每轮游戏给定两堆石子的个数,两人轮流操作,每次操作可以选择一堆取任意数量的石子,也可以选两堆取,要求两堆取的石子数之差的绝对值小于K,不能操作者为输,问先手的胜负情况. 解题思路:傻逼先手才一次取完,那样的话对手直接将另一堆取光不就傻逼了.所以先手就有一个取石子的最优策略,当两堆石子的数量差小于等K的时候,先手可以一次性取完所有的. 我们设f(x)为一堆石子的数量为x时的必败态,即x,f(x),为先手必败态,x<f

UVA 1559 - Nim(博弈dp)

UVA 1559 - Nim 题目链接 题意:一开始有s个石子,2n个人轮流取石子,每个人有个最大能取数目,2n个人奇数一队,偶数一队,取到最后一个石子的队输,问谁赢 思路:记忆化搜索,每个人取的时候对应的后继状态如果有一个必败态,则该状态为必胜态,如果都是必胜态,则该状态为必败态 代码: #include <stdio.h> #include <string.h> int n, s, m[25], dp[25][10005]; int dfs(int now, int state

UVA 10561 - Treblecross(博弈SG函数)

UVA 10561 - Treblecross 题目链接 题意:给定一个串,上面有'X'和'.',可以在'.'的位置放X,谁先放出3个'X'就赢了,求先手必胜的策略 思路:SG函数,每个串要是上面有一个X,周围的4个位置就是禁区了(放下去必败),所以可以以X分为几个子游戏去求SG函数的异或和进行判断,至于求策略,就是枚举每个位置就可以了 代码: #include <stdio.h> #include <string.h> #include <algorithm> usi

Uva 10404-Bachet&#39;s Game(博弈)

题目链接:点击打开链接 在DP专题里刷到的,看着像博弈就水过去了.. 题意:n件物品,两个人轮流取,每次取的数量必须为一个集合s(集合里肯定含有1)里的一个数字,最后不能取者输(即取走最后一件物品者胜). 思路:递推.设 w[i] 为有i件物品时的状态,w[i]=1代表先手必胜,w[i]=0代表先手必败.可以知道w[1]=1,递推生成所有状态. 可以知道对于一个状态,如果他的后继存在必败状态,则该状态为必胜状态:如果该状态的所有后继都为必胜状态,那么该状态为必败状态. #include <alg

UVA 1558 - Number Game(博弈dp)

UVA 1558 - Number Game 题目链接 题意:20之内的数字,每次可以选一个数字,然后它的倍数,还有其他已选数的倍数组合的数都不能再选,谁先不能选数谁就输了,问赢的方法 思路:利用dp记忆化去求解,要输出方案就枚举第一步即可,状态转移过程中,选中一个数字,相应的变化写成一个函数,然后就是普通的博弈问题了,必胜态之后必有必败态,必败态之后全是必胜态 代码: #include <stdio.h> #include <string.h> const int N = 105

UVA 1557 - Calendar Game(博弈dp)

UVA 1557 - Calendar Game 题目链接 题意:给定一个日期,两个人轮流走,每次可以走一月或者一天,问最后谁能走到2001.11.4这个日子 思路:记忆化搜索,对于每个日期,如果下两个状态有一个非必胜态,那么这个状态是必胜态,如果后继状态都是必胜态,那么该状态为必败态 代码: #include <stdio.h> #include <string.h> const int day[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31,

UVA 847 - A Multiplication Game(博弈)

UVA 847 - A Multiplication Game 题目链接 题意:一个数一开始是1,每次轮流乘2-9,谁先大于n谁就赢,问谁胜 思路:博弈,找出必胜态,2-9为stan,10-18为ollie,19-162为stan...发现都是乘2乘9交替 代码: #include <stdio.h> #include <string.h> #include <math.h> long long n; bool judge(long long n) { long lon

UVA 11534 - Say Goodbye to Tic-Tac-Toe(博弈sg函数)

UVA 11534 - Say Goodbye to Tic-Tac-Toe 题目链接 题意:给定一个序列,轮流放XO,要求不能有连续的XX或OO,最后一个放的人赢,问谁赢 思路:sg函数,每一段...看成一个子游戏,利用记忆化求sg值,记忆化的状态要记录下左边和右边是X还是O即可 代码: #include <stdio.h> #include <string.h> const int N = 105; int t, sg[3][3][N]; char str[N]; int ge

uva 1557 - Calendar Game(博弈)

题目链接:uva 1557 - Calendar Game 题目大意:给定一个日期,每次可以选择加一个月,或者加一天,加一个月的前提是下一个月有对应的日期,比如1.30加一个月变成2.30是不合法的,日期上限为2001.11.4.两个人轮流操作,不能操作为失败. 解题思路:dp[y][m][d]表示对应日期是否为先手必胜.预先处理即可,注意细节,包括闰年等.分享代码. #include <cstdio> #include <cstring> #include <algorit