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]表示sumt=i时包含的sumw  对于一个重w效力t的物体  g[i]->g[i+t]  同时所有sumw->sumw+w  这样相当于少for了一维  然后再把g[i+t]中从0变成1的sumw的f数组对应记录一下

PS:

__builtin_ctz() 从ftiasch代码中看到了这个函数  蛮方便的  这是对于一个unsigned int返回二进制最后一个1后有几个0  那么__builtin_ctzll()则是针对unsigned long long的

做了3天数模高教社杯比赛  累成狗不说  刷题节奏完全断了……  要快点找回感觉……  补题补题补题补题……

代码:

#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<vector>
using namespace std;
typedef long long LL;
#define Q 401
#define N 51
#define M 200001
#define inf 2147483647
#define lowbit(x) (x&(-x))

int t, n, q;
short f[N][M];
LL g[M];
int v[Q], w[Q], aw[Q], av[Q];

int main() {
	int i, j, fv, fw;
	LL k, tmp;
	scanf("%d", &t);
	while (t--) {
		memset(f, 0, sizeof(f));
		memset(g, 0, sizeof(g));
		g[0] = 1;
		scanf("%d%d", &n, &q);
		for (i = 1; i <= n; i++)
			scanf("%d%d", &w[i], &v[i]);
		for (i = 1; i <= q; i++)
			scanf("%d%d", &aw[i], &av[i]);
		for (i = 1; i <= n; i++) {
			for (j = M - 1; j >= v[i]; j--) {
				k = ((g[j - v[i]] << w[i]) & ((1LL << N) - 1)) | g[j];
				tmp = k ^ g[j];
				g[j] = k;
				while (tmp) {
					f[__builtin_ctzll(tmp)][j] = i;
					tmp ^= lowbit(tmp);
				}
			}
		}
		for (i = 1; i <= q; i++) {
			fw = aw[i];
			fv = av[i];
			if (f[fw][fv]) {
				j = f[fw][fv];
				printf("%d", j);
				fw -= w[j];
				fv -= v[j];
				for (; fw && fv;) {
					j = f[fw][fv];
					printf(" %d", j);
					fw -= w[j];
					fv -= v[j];
				}
				putchar('\n');
			} else
				puts("No solution!");
		}
	}
	return 0;
}
时间: 2024-10-11 23:33:38

ZOJ 3812 We Need Medicine的相关文章

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

这道题就题意来说其实就是一道简单的记录路径的0,1背包,告诉你n个物品,每种物品只能取一次,再有q个询问,问你是否能在满足选出物品的w之和为m的情况下,满足t之和为s的情况,若可以则任意输出一种方案. 因此我们可以设计状态,dp[i][j][k]为前i个物品选出部分,当t之和为j时,w之和为k的情况能否满足,若存在方案则为1,不存在则为0.而状态的转移方程也是很简单. dp[i][j+t[i]][k+w[i]] = dp[i-1][j][k].但是这样会超时,超时的原因是因为大量进行了重复的动作

2015南阳CCPC L - Huatuo&#39;s Medicine 水题

L - Huatuo's Medicine Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 无 Description Huatuo was a famous doctor. He use identical bottles to carry the medicine. There are different types of medicine. Huatuo put medicines into the bottles and chain these b

概率dp ZOJ 3640

Help Me Escape Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Practice ZOJ 3640 Appoint description:  System Crawler  (2014-10-22) Description Background     If thou doest well, shalt thou not be accepted? an