zoukankan      html  css  js  c++  java
  • JZOJ 5778

    Description

    被污染的灰灰草原上有羊和狼。有N只动物围成一圈,每只动物是羊或狼。

    该游戏从其中的一只动物开始,报出[1,K]区间的整数,若上一只动物报出的数是x,下一只动物可以报[x+1,x+K]区间的整数,游戏按顺时针方向进行。每只动物报的数字都不能超过M。

    若一只动物报了M这个数,它所在的种族就输了。问以第i只动物为游戏的开始,最后哪种动物会赢?

    Input

    第一行输入三个正整数N,M,K。

    接下来一行N个正整数,分别表示N只动物的种类,以顺时针的方向给出。0代表羊,1代表狼。

    Output

    一行输出N个整数,表示若从第i只动物开始,赢的动物的种类。同上,0代表羊,1代表狼。

    Sample Input

    Input 1

    2 9 2
    0 1


    Input 2

    6 499 5
    1 0 0 1 1 0


    Input 3

    10 100 10
    0 0 0 1 1 1 1 0 1 1


    Sample Output

    Output 1

    0 1


    Output 2

    0 1 1 1 1 0


    Output 3

    1 1 1 1 1 1 1 1 1 1


    Data Constraint

    对于60%的数据,1 ≤ N, M, K ≤ 500。

    对于100%的数据,1 ≤ N, M, K ≤ 5000。


    一开始以为结论博弈题,玩了玩发现好像并不是

    又以为是 SG 函数,心想只能打暴力了

    yy 了一下写了个 dp  (差点就写对了?

    一开始觉得破环成链复制出来 m 个很虚,也没敢接着想

    反正状态是错的:f[i][j] 表示第 i 个数第 j 个人选是必胜还是必败

    还有带个线段树优化成 O(n ^ 2 * logn)

    居然还有8分

    正解是这样的

    f[i][j] 表示 在位置 i 这个人选择 j 这个数是必胜还是必败

    最多每个人都选择增大 1 ,所以将人复制成为 n + m 个

    边界:所有人选 m 都是必败,第 n + m - 1 个人只能选 1, 也是必败,就不用更新他了

    倒着递推出之前的

    f[i][j] 从 f[i][j + 1] ~ f[i][j + k] 更新

    判断上一个人是不是队友,是队友只要有必胜态,此状态还是必胜

    不是队友只要有必胜态,此状态为必败态,否则必胜

    什么前缀和线段树什么的随便优化一下就好了


    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cctype>
    #include<cstdio>
    using namespace std;
    
    const int MAXN = 5005;
    
    int n, m, k;
    int per[MAXN << 1], f[MAXN << 1][MAXN];
    
    inline int rd() {
    	register int x = 0;
    	register char c = getchar();
    	while(!isdigit(c)) c = getchar();
    	while(isdigit(c)) {
    		x = x * 10 + (c ^ 48);
    		c = getchar();
    	}
    	return x;
    }
    
    int main() {
    	freopen("vode.in", "r", stdin);
    	freopen("vode.out", "w", stdout);
    	n = rd(); m = rd(); k = rd();
    	for(int i = 1; i <= n; ++i) per[i] = rd();
    	int ptr = n;
    	while(ptr < m + n) {
    		++ptr;
    		per[ptr] = per[ptr - n];
    	}
    	for(int i = n + m - 2; i >= 1; --i) {
    		int pre = 0;
    		for(int j = m - 1; j >= 1; --j) {
    			f[i][j] = ((per[i] == per[i + 1]) ? (!(pre == 0)) : (pre == 0)); 
    			pre += f[i + 1][j];
    			if(m - j + 1 >= k) pre -= f[i + 1][j + k];
    		}
    	}
    	for(int i = 1; i <= n; ++i) {
    		bool win = false;
    		for(int j = 1; j <= k; ++j) win |= f[i][j];
    		printf("%d ", win ? per[i] : (per[i] ^ 1));
    	}
    	return 0;
    }
    

      

    禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载 ,用户转载请注明出处:https://www.cnblogs.com/xcysblog/
  • 相关阅读:
    ASP.NET AJAX入门系列(1):概述
    ASP.NET中常用的文件上传下载方法
    Asp.net中DataBinder.Eval用法的总结
    ASP.NET AJAX入门系列(6):UpdateProgress控件简单介绍
    ASP.NET AJAX入门系列(8):自定义异常处理
    Javascrip常用语句
    26个常用的方法优化 ASP.NET 的性能
    JavaScript倒计时组件
    jQuery.buildFragment源码分析
    jQuery.Callbacks源码解读
  • 原文地址:https://www.cnblogs.com/xcysblog/p/9446016.html
Copyright © 2011-2022 走看看