参考:http://blog.csdn.net/qian99/article/details/39138329
参考的链接里说明得很好,注释也很好。。。thanks for sharing
朴素的想法不难,dp[i][j][k]类似背包做法即可。
但朴素思想复杂度过高。
这里主要是用到 dif 那个变量,只枚举新增的集合。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <vector> #include <set> #include <queue> #include <map> using namespace std; #define MP make_pair #define ll long long #define inf 0x3f3f3f3f #define maxn 100010 #define maxm 200010 ll sta[200010]; int ans[55][200010]; map<ll,int>mp; int a[410],b[410]; int main(){ for(int i=0;i<=50;++i) mp.insert(MP(1ll<<i,i)); int t,n,q; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&q); memset(sta,0,sizeof(sta)); memset(ans,-1,sizeof(ans)); sta[0] = 1; for(int i=1;i<=n;++i){ scanf("%d%d",a+i,b+i); for(int j=200000;j>=b[i];--j){ ll st = sta[j]; sta[j] |= (sta[j-b[i]]<<a[i]) & ((1ll<<52)-1); ll dif = st^sta[j]; while(dif){ ll low = dif&(-dif); int cnt = mp[low]; ans[cnt][j] = i; dif -= low; } } } for(int i=0;i<q;++i){ int mi,si; scanf("%d%d",&mi,&si); if(ans[mi][si]==-1) puts("No solution!"); else { int idx = ans[mi][si]; printf("%d",idx); mi -= a[idx]; si -= b[idx]; while(mi){ int idx = ans[mi][si]; printf(" %d",idx); mi -= a[idx]; si -= b[idx]; } puts(""); } } } return 0; }