首页 > 代码库 > ZOJ 3812 We Need Medicine(dp、背包、状态压缩、路径记录)

ZOJ 3812 We Need Medicine(dp、背包、状态压缩、路径记录)

参考: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 200010ll 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;}

 

ZOJ 3812 We Need Medicine(dp、背包、状态压缩、路径记录)