题目
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3812
分析
最裸的dp就是f[i][j][k],然后把k压成二进制变成f[i][j]。 K用bitset呀200000那维。
然后将i/10 输出时2^10暴力。
代码
#include<stdio.h> #include<stdlib.h> #include<algorithm> #include<iostream> #include<bitset> using namespace std; typedef bitset<200010> bs; bs g[45][55]; int d2[31],w[2100],t[2100],n,q,tot,ans[2100],T,m; int dfs2(int a,int b,int c,int d,int e,int f,int ww) { if(e>b||f>ww) return 0; if(c+d>n||d>10) return g[a-1][b-e][ww-f]; int k=dfs2(a,b,c,d+1,e,f,ww); if(k&1) return k; return dfs2(a,b,c,d+1,e+w[c+d],f+t[c+d],ww)|d2[d]; } int main() { scanf("%d",&T); d2[0]=1; for(int i=1;i<=21;++i) d2[i]=d2[i-1]<<1; while(T--) { scanf("%d%d",&n,&q); for(int i=1;i<=n;++i) scanf("%d%d",&w[i],&t[i]); m=(n-1)/10+1; g[0][0].set(0); for(int i=1;i<=m;++i) { for(int j=0;j<=50;++j) g[i][j]=g[i-1][j]; for(int j=(i-1)*10+1;j<=min(i*10,n);++j) for(int k=50;k>=w[j];--k) { bs tt=g[i][k-w[j]]<<t[j]; g[i][k]|=tt; } } while(q--) { int a,b; tot=0; scanf("%d%d",&a,&b); if(g[m][a][b]) { for(int i=m;i;--i) { int k=dfs2(i,a,(i-1)*10,1,0,0,b); k>>=1; for(int j=1;k;k>>=1,++j) if(k&1) ans[++tot]=(i-1)*10+j, a-=w[ans[tot]],b-=t[ans[tot]]; } sort(ans+1,ans+tot+1); for(int i=1;i<tot;++i) printf("%d ",ans[i]); printf("%d\n",ans[tot]); } else printf("No solution!\n"); } } return 0; }