5778. 【NOIP提高A组模拟2018.8.8】没有硝烟的战争

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代表狼。
 
Solutions

我们可以设 dp[i][j]=0/1 来表示第 i 只动物报的数字是 j,是否有必胜策略。

0 表示没有必胜策略,1 表示有。

边界条件就是 dp[][m]=0 Dp[i][j]怎么求?

假如 i 和 i+1 是同一个种群,那么只需要判断 dp[i+1][j+1…j+k]是否存在必胜策略,如果存在,那么 dp[i][j]=1.

同样的,假如 i 和 i+1 不是同一个种群,那么只需要判 断 dp[i+1][j+1…j+k]是否存在必胜策略,如果存在,那 么 dp[i][j]=0.

判断 dp[i+1][j+1…j+k]是否存在必胜策略,只需要用一 个后缀和辅助即可。

然后对于每一个动物,你只需要知道,dp[i][1…k]是否 有必胜策略就行了。

代码

 1 var
 2   n,m,k:longint;
 3   a:array [0..5001] of longint;
 4   f,ans:array [0..5001,0..5001] of longint;
 5 function min(o,p:longint):longint;
 6 begin
 7   if o<p then exit(o);
 8   exit(p);
 9 end;
10 
11 procedure init;
12 var
13   i:longint;
14 begin
15   readln(n,m,k);
16   for i:=1 to n do
17     read(a[i]);
18 end;
19 
20 procedure main;
21 var
22   i,j,l:longint;
23 begin
24   fillchar(f,sizeof(f),0);
25   for j:=m-2 downto 0 do
26     for i:=1 to n do
27       begin
28         l:=i+1;
29         if l>n then l:=1;
30         if a[l]=a[i] then
31           begin
32             if ans[l,j+1]-ans[l,min(j+k,m-1)+1]>0 then
33               f[i,j]:=1;
34           end else
35           begin
36             if ans[l,j+1]-ans[l,min(j+k,m-1)+1]<min(j+k,m-1)-(j+1)+1 then
37               f[i,j]:=1;
38           end;
39         ans[i,j]:=ans[i,j+1]+f[i,j];
40       end;
41 end;
42 
43 procedure print;
44 var
45   i:longint;
46 begin
47   for i:=1 to n do
48     if f[i,0]=1 then write(a[i],' ')
49                 else write(a[i] xor 1,' ');
50 end;
51 
52 begin
53   assign(input,'vode.in');
54   assign(output,'vode.out');
55   reset(input);
56   rewrite(output);
57   init;
58   main;
59   print;
60   close(input);
61   close(output);
62 end.
原文地址:https://www.cnblogs.com/zyx-crying/p/9445587.html