UVA 1558 - Number Game(博弈dp)

UVA 1558 - Number Game

题目链接

题意:20之内的数字,每次可以选一个数字,然后它的倍数,还有其他已选数的倍数组合的数都不能再选,谁先不能选数谁就输了,问赢的方法

思路:利用dp记忆化去求解,要输出方案就枚举第一步即可,状态转移过程中,选中一个数字,相应的变化写成一个函数,然后就是普通的博弈问题了,必胜态之后必有必败态,必败态之后全是必胜态

代码:

#include <stdio.h>
#include <string.h>

const int N = 1050005;
int t, n, w, start, dp[N], ans[25], an;

int getnext(int state, int x) {
	for (int i = x; i <= 20; i += x)
 		if (state&(1<<(i - 2)))
   			state ^= (1<<(i - 2));
	for (int i = 2; i <= 20; i++) {
		if (state&(1<<(i - 2))) {
			for (int j = x; i - j >= 2; j += x) {
				if (!(state&(1<<(i - j - 2)))) {
					state ^= (1<<(i - 2));
					break;
				}
   			}
  		}
 	}
 	return state;
}

int dfs(int state) {
	if (dp[state] != -1) return dp[state];
	if (state == 0) return dp[state] = 0;

	for (int i = 2; i <= 20; i++) {
		if (state&(1<<(i - 2))) {
			if (dfs(getnext(state, i)) == 0)
				return dp[state] = 1;
  		}
 	}
 	return dp[state] = 0;
}

int main() {
	int cas = 0;
	scanf("%d", &t);
	memset(dp, -1, sizeof(dp));
	while (t--) {
		start = 0; an = 0;
		scanf("%d", &n);
		for (int i = 0; i < n; i++) {
			scanf("%d", &w);
			start |= (1<<(w - 2));
  		}
  		for (int i = 2; i <= 20; i++) {
  			if (start&(1<<(i - 2))) {
  				if (dfs(getnext(start, i)) == 0)
  					ans[an++] = i;
     		}
    	}
    	printf("Scenario #%d:\n", ++cas);
    	if (an) {
    		printf("The winning moves are:");
    		for (int i = 0; i < an; i++)
    			printf(" %d", ans[i]);
  			printf(".\n");
     	}
     	else printf("There is no winning move.\n");
     	printf("\n");
 	}
	return 0;
}

UVA 1558 - Number Game(博弈dp),布布扣,bubuko.com

时间: 2024-12-26 17:23:35

UVA 1558 - Number Game(博弈dp)的相关文章

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 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 10891 (博弈+DP) Game of Sum

最开始的时候思路就想错了,就不说错误的思路了. 因为这n个数的总和是一定的,所以在取数的时候不是让自己尽可能拿的最多,而是让对方尽量取得最少. 记忆化搜索: d(i, j)表示原序列中第i个元素到第j个元素构成的子序列,先手取数能够得到的最大值. sum(i, j) 表示从第i个元素到第j个元素的和 因为要让对手获得最小的分数,所以状态转移方程为: d(i, j) = sum(i, j) - min{d(枚举所有可能剩给对手的序列), 0(0代表全部取完)} s数组保存a中前i个元素的和,这样s

UVA 14000 Lighting System Design(DP)

You are given the task to design a lighting system for a huge conference hall. After doing a lot of calculation & sketching, you have figured out the requirements for an energy-efficient design that can properly illuminate the entire hall. According

UVA 10003 Cutting Sticks(区间dp)

Description  Cutting Sticks  You have to cut a wood stick into pieces. The most affordable company, The Analog Cutting Machinery, Inc. (ACM), charges money according to the length of the stick being cut. Their procedure of work requires that they onl

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

uva 10891 Game of Sum (DP)

uva 10891 Game of Sum (DP) This is a two player game. Initially there are n integer numbers in an array and players A and B get chance to take them alternatively. Each player can take one or more numbers from the left or right end of the array but ca

Uva 10817 Headmaster&#39;s Headache (DP+ 状态压缩)

Problem D: Headmaster's Headache Time limit: 2 seconds The headmaster of Spring Field School is considering employing some new teachers for certain subjects. There are a number of teachers applying for the posts. Each teacher is able to teach one or

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