动态规划水题。。
令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