[第二场(2)]Vode

题目描述
众所周知,山羊和绵羊多年一来都在为他们的田地斗争。经过多年的争夺,山羊的领导人决定和绵羊的领导人见面,试图找到和平解决问题的方法。经过几个小时的讨论,他们决定在田地上都进行一场比赛,谁获胜谁就获得这块田地。

游戏内容是这样的:游戏总共有N只动物(可以使山羊或绵羊)他们围成一个圈(山羊和绵羊的确切顺序由他们的领导人决定),在第i个动物之后是第i+1个动物,第N个动物后是第1个动物。开始时,选择[1,K]之间的任何数字,但这个数字不能大于M。如果选择的这个数字是j,那么,下一个动物只能选择[j+1,j+K]之间的数字,同样这个数字不能大于M。换句话说,每个动物能够选择的数字,最小为1,最大为K,且这个数字不能比前面动物所选择的数字小,且这个数字不能大于M。当这个动物只能选择M或比M大的数时,它的团队(绵羊或者山羊)就会输。

如果山羊和绵羊都选择最佳的方式进行比赛,对于每一个i(1≤i≤N),如果从第i个动物开始,谁会赢得这场比赛。
输入格式
第一行输入三个数字N、M、K(1≤N,M,K≤5000)。

接下来输入N个只包含01的数字,0表示绵羊,1表示山羊。
输出格式
输出N个数字,表示从第i个动物开始比赛谁会获胜。如果绵羊获胜,则输出0,否则,输出1。
样例
样例输入1

2 9 2
0 1
样例输出1

0 1
样例输入2

6 499 5
1 0 0 1 1 0
样例输出2

0 1 1 1 1 0
样例输入3

10 100 10
0 0 0 1 1 1 1 0 1 1
样例输出3

1 1 1 1 1 1 1 1 1 1
数据范围与提示
对于样例1:如果从第1个动物开始(即绵羊),它可以选择数字范围是[1,2],它选择2,那么,山羊接下来只能选择3或者4.不管山羊选择3还是4,绵羊都能选择5。接下来,山羊能选择6或者7,同样的,无论山羊怎么选,绵羊都能选择8。接下来,山羊只能选择9,那么,它就会输掉比赛。

解题思路

虽然不会博弈,但还是看了出来。
其实也挺简单,我们定义dp[i][j]表示第i个人还有j个数字可以选是胜还是否
1胜0负
如果他的下一个人是队友
那么只要它下一个人从j - 1到j - 1 - k有一个是必胜的,那么它这一个状态肯定必胜,否则必败
如果是敌人
那么只要那个人在选择的那一个区间有一个是必败,那么当前人这一个状态就必胜。
所以就完了。再用前缀和优化一下

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
using namespace std;
bool dp[5005][5005];
int n,m,k,sum[5005][5005],a[5005];
int main(){
	scanf ("%d%d%d",&n,&m,&k);
	for (int i = 1;i <= n;i ++)
		scanf ("%d",&a[i]);
	for (int j = 1;j <= m;j ++){
		for (int i = 1;i <= n;i ++){
			int net = i + 1;
			if (net > n)
				net = 1;
			if (a[i] != a[net]){
				if (sum[net][j - 1] - sum[net][max(0,j - k - 1)] != k)
					dp[i][j] = 1;
				else 
					dp[i][j] = 0;
			}
			else{
				if (sum[net][j - 1] - sum[net][max(0,j - k - 1)] == 0)
					dp[i][j] = 0;
				else 
					dp[i][j] = 1;
			}
			sum[i][j] += sum[i][j - 1] + dp[i][j];
		}
	}
	for (int i = 1;i <= n;i ++){
		if (a[i] == 1){
			if (dp[i][m - 1])
				printf("1 ");
			else 
				printf("0 ");
		}
		else {
			if (dp[i][m - 1])
				printf("0 ");
			else 
				printf("1 ");
		}
	}
	printf("
");
}
原文地址:https://www.cnblogs.com/lover-fucker/p/13566656.html