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 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;
}
时间: 2024-11-07 09:09:25

ZOJ 3812 We Need Medicine(dp、背包、状态压缩、路径记录)的相关文章

zoj 3812 We Need Medicine(01背包)

题目链接:zoj 3812 We Need Medicine 题目大意:有n中化学成分,每种成分要么选取重量Wi,获得Ti的TEV值,要么不取,获得0的TEV值.现在对于每种病 毒,要求配置质量为Mi的药物,并且TEV值为Si,求化学成分组成. 解题思路:看了别人的题解,以前居然不知道背包转移可以用二进制. 因为质量总共才50,所以用一个long long的二进制数表示说哪些质量是可祖长的,这样的话只要开一个20W的数组 s,s[i]表示说TEV值为i时质量可以为多少.然后每次在用lowbit处

zoj 3812 We Need Medicine (dp 状压)

先贴一下转载的思路和代码,,,:http://blog.csdn.net/qian99/article/details/39138329 状压dp博大精深啊,以后看到n<=50都可以往状压上想,orz We Need Medicine Time Limit: 10 Seconds                                     Memory Limit: 65536 KB                                                   

ZOJ 3812 We Need Medicine 01背包+位优化

题目链接:点击打开链接 #include <cstdio> #include <algorithm> #include <iostream> #include <cstring> #include <map> typedef unsigned long long ll; using namespace std; const int N = 400 + 1; const int M = 200000 + 1; int t[N], w[N], g[5

ZOJ 3812 We Need Medicine(牡丹江网络赛D题)

ZOJ 3812 We Need Medicine 题目链接 思路:dp[i][j][k]表示第i个物品,组成两个值为j和k的状态,这样会爆掉,所以状态需要转化一下 首先利用滚动数组,可以省去i这维,然后由于j最大记录到50,所以可以把状态表示成一个二进制数s,转化成dp[k] = s,表示组成k状态能组成s,这样空间复杂度就可以接受了,然后这题时限还可以,就这样去转移,然后记录下路径即可 代码: #include <cstdio> #include <cstring> #incl

hdu6149 Valley Numer II 分组背包+状态压缩

/** 题目:hdu6149 Valley Numer II 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6149 题意: 众所周知,度度熊非常喜欢图. 为了形成山谷,首先要将一个图的顶点标记为高点或者低点. 标记完成后如果一个顶点三元组<X, Y, Z>中, X和Y之间有边,Y与Z之间也有边,同时X和Z是高点,Y是低点,那么它们就构成一个valley. 度度熊想知道一个无向图中最多可以构成多少个valley,一个顶点最多只能出现在一个valley

hdu6125 Free from square 分组背包+状态压缩

/** 题目:hdu6125 Free from square 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6125 题意: 从不大于n的所有正整数中选出至少1个且至多k个使得乘积不包含平方因子,对10^9+7取模. 1≤n,k≤500. 思路: 分组背包+状态压缩 把n个数分成若干组,互斥的放在同一组. 一开始把所有含平方因子的数去除掉,剩下的进行分组. <sqrt(500)的八个素因子,编成八组,分别为包含2,3,5,7,11,13,17,19素

ZOJ 1639 Hang Up the System (状态压缩)

Hang Up the System Time Limit: 2 Seconds      Memory Limit: 32768 KB You're going to design a multi-task operating system for an embedded system. Because the resources are limited on this mini computer, parallel running of some programs will probably

HDU 4352 XHXJ&amp;#39;s LIS(数位dp&amp;amp;状态压缩)

题目链接:[kuangbin带你飞]专题十五 数位DP B - XHXJ's LIS 题意 给定区间.求出有多少个数满足最长上升子序列(将数看作字符串)的长度为k. 思路 一个数的上升子序列最大长度为10,所以每个上升子序列的状态都能够用10个二进制位来表示. 上升子序列的变化能够用LIS的方式来更新. dp[len][num][k] len为当前的位,num为当前上升子序列的状态.k表示子序列的长度. next[s][num]为记录预处理的子序列的状态变化. cnt [num]记录各个状态的最

台州 OJ 2537 Charlie&#39;s Change 多重背包 二进制优化 路径记录

描述 Charlie is a driver of Advanced Cargo Movement, Ltd. Charlie drives a lot and so he often buys coffee at coffee vending machines at motorests. Charlie hates change. That is basically the setup of your next task. Your program will be given numbers

POJ-2923 Relocation---01背包+状态压缩

题目链接: https://vjudge.net/problem/POJ-2923 题目大意: 有n个货物,给出每个货物的重量,每次用容量为c1,c2的火车运输,问最少需要运送多少次可以将货物运完 思路: 第一次做状态压缩(状态压缩基础知识传送门) 本题的解题思路是先枚举选择若干个时的状态,总状态量为1<<n,判断这些状态集合里的那些物品能否一次就运走,如果能运走,那就把这个状态看成一个物品.预处理完能从枚举中找到tot个物品,再用这tol个物品中没有交集(也就是两个状态不能同时含有一个物品)