[dp][后缀和] Jzoj P5778 没有硝烟的战争
题解
- 首先,可以破坏为链,在n后返回到1
- 设f[i][j]为前i个动物 报的数字为j 是否有必胜策略(0表示没有 1表示有)
- 那么怎么求f数组
- 如果当前i和i+1是同一种动物
- 那只要判断f[i+1][j+1...+k]有没有必胜策略,如果有f[i][j]=1
- 如果当前i和i+1不是同一种动物
- 那只要判断f[i+1][j+1...+k]有没有必胜策略,如果有f[i][j]=0
- 那么判断f[i+1][j+1...+k]有没有必胜策略,只要用一个后缀和统计就好了
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <cmath> 5 using namespace std; 6 int f[5010][5010],sum[5010][5010],n,m,q,a[5010]; 7 int quan(int x) {if (x==n) return 1; else return x+1;} 8 int main() 9 { 10 //freopen("vode.in","r",stdin); 11 //freopen("vode.out","w",stdout); 12 scanf("%d%d%d",&n,&m,&q); 13 for (int i=1;i<=n;i++) scanf("%d",&a[i]); 14 for (int j=m-2;j>=0;j--) 15 for (int i=1;i<=n;i++) 16 { 17 int mn=j+1,mx=min(j+q,m-1); 18 f[i][j]=(((a[i]^a[quan(i)])&&sum[quan(i)][mn]-sum[quan(i)][mx+1]<mx-mn+1)||(!(a[i]^a[quan(i)])&&sum[quan(i)][mn]-sum[quan(i)][mx+1]>0)); 19 sum[i][j]=sum[i][j+1]+f[i][j]; 20 } 21 for (int i=1;i<=n;i++) printf("%d ",(1-(f[i][0]^a[i]))); 22 return 0; 23 }