动态规划水题。。
令f[i][j]表示考虑第1~i个位置,i~i+4位置上面移走或者不移走的状态为j时的最优解。预处理g[i][j]表示在第i位状态为j时的收益,这样就可以O(1)转移了。
由于题目是环,因此要求首尾的部分状态要重叠;枚举前4位固定不变的状态在进行dp。时间复杂度O(2^4*N*2^5)=O(2^9N)。
(随手写一发就rk2了什么鬼。。。)
AC代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,a[50005],f[10005][32],g[10005][32]; bool ok[50005][32];
const int bin[5]={1,2,4,8,16};
int read(){
int x=0; char cr=getchar();
while (cr<'0' || cr>'9') cr=getchar();
while (cr>='0' && cr<='9'){ x=x*10+cr-'0'; cr=getchar(); }
return x;
}
int main(){
n=read(); m=read(); int i,j,k,x,y;
for (i=1; i<=m; i++){
a[i]=read();
j=read(); k=read(); x=y=0;
while (j--) x|=bin[(read()+n-a[i])%n];
while(k--) y|=bin[(read()+n-a[i])%n];
for (j=0; j<32; j++)
if ((j&x) || ((31^j)&y)){ ok[i][j]=1; g[a[i]][j]++; }
}
int ans=0;
for (i=0; i<16; i++){
memset(f[0],200,sizeof(f[0]));
f[0][i<<1]=0;
for (j=1; j<=n; j++)
for (k=0; k<32; k++) f[j][k]=max(f[j-1][(k&15)<<1],f[j-1][(k&15)<<1|1])+g[j][k];
ans=max(ans,max(f[n][i<<1],f[n][i<<1|1]));
}
printf("%d\n",ans);
return 0;
}
by lych
2016.6.1