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[51][M], ans[N], dep;
ll d[M];
map<ll, int> id;

char ch;
void get(int& z) {
	while ((ch = getchar()) > '9' || ch < '0');
	z = ch - '0';
	while ((ch = getchar()) >= '0' && ch <= '9')
		z = z * 10 + ch - '0';
}

int main() {
	for (ll i = 1; i <= 50; ++i)
		id[1ll << i] = i;

	int cas, n, m, x, y;
	ll v, mx = (1ll << 51) - 1;

	get(cas);
	while (cas -- > 0) {
		memset(d, 0, sizeof d);
		d[0] = 1;

		memset(g, -1, sizeof g);
		get(n); get(m);
		for (int i = 0; i < n; ++i) {
			get(w[i]); get(t[i]);
			for (int j = M - t[i] - 1; j >= 0; --j)
				if (d[j] > 0) {
					v = d[j + t[i]];
					d[j + t[i]] |= (d[j] << w[i]) & mx;
					v = v ^ d[j + t[i]];
					while (v > 0) {
						if (v & 1) {
							v = v & (v - 1);
							continue;
						}
						x = id[v & (v - 1) ^ v];
						g[x][j + t[i]] = i;

						v = v & (v - 1);
					}
				}
			//g[w[i]][t[i]] = i;
		}

		while (m -- > 0) {
			get(x); get(y);
			if (g[x][y] >= 0) {
				dep = 0;
				while (x > 0 && y > 0) {
					ans[dep++] = g[x][y];
					x -= w[ans[dep - 1]];
					y -= t[ans[dep - 1]];
				}
				for (int i = dep - 1; i >= 0; --i) {
					if (i == 0)
						printf("%d\n", ans[i] + 1);
					else
						printf("%d ", ans[i] + 1);
				}
			} else
				puts("No solution!");
		}
	}
	return 0;
}
时间: 2024-10-25 14:10:45

ZOJ 3812 We Need Medicine 01背包+位优化的相关文章

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 位优化 巧妙记录路径)

We Need Medicine Time Limit: 10 Seconds      Memory Limit: 65536 KB      Special Judge A terrible disease broke out! The disease was caused by a new type of virus, which will lead to lethal lymphoedema symptom. For convenience, it was namedLL virus.

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

ZOJ 3812 We Need Medicine

题意: 一个物品重w效力t  给出所有n个物品  有q个询问  每个询问输出w的和为m同时t的和为s的方案 思路: 明显就是01背包  只不过一个东西在两个维度上有价值  由于w只有50因此可以状压 先想如何输出方案  利用f[i][j]表示sumw=i同时sumt=j时候装进包里的最后一个物品  那么输出这个物品后i和j都减去这个物品的w和t  就可以到达新的状态  这样可以一直到背包为空  最多循环50次 最难得是dp过程  之前提到状压  这题精髓就是状压后50位状态一起转移  用g[i]

【背包专题】F - Ahui Writes Word hdu3732【01背包+二进制优化】

We all know that English is very important, so Ahui strive for this in order to learn more English words. To know that word has its value and complexity of writing (the length of each word does not exceed 10 by only lowercase letters), Ahui wrote the

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 <algo

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 3211 Dream City DP 01背包 经典问题

题目大意:JAVAMAN 到梦幻城市旅游见到了黄金树,黄金树上每天回结出金子.已经有n棵树,JAVAMAN要停留m天,每天只能砍掉一棵树,砍掉树后就能得到树上的黄金.给定n棵树上原有的黄金a[i]和每天可以新增加的黄金b[i],求他最多可以得到多少黄金.中途如果有1天不砍树的话,之后的日子久不能砍树,所有最好每天都砍树,或者直到树被砍完. 这个其实是个背包问题,把日期看成背包的容量.然后n棵树当成n个物品. 假设我们取得由某 m 棵树组成的最优解.如果先砍的树的b值比后砍的树的b值大, 那么我们

01背包的优化问题

通过不断的去模拟代码的运行 对背包问题有了更深的理解 sum[i][j]=max(sum[i-1][j],sum[i-1][j-x[i]]+v[i]); 实际上就是数据的不断更新过程 在上一子问题的基础上 对该子问题每个空间大小能放的最多价值进行更新 然后使用于下一个子问题  由于每个子问题都是最优解 最终得到的解就是最优解 下午的背包刚入手 用的是二维数组 有一定程度的浪费空间 对于一个子问题的每个空间对应的最佳价值 可以通过从高位到地位逆序的写法(下一个子问题求每个空间大小的最佳价值要使用的