背包
01背包
饭卡
电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)。所以大家都希望尽量使卡上的余额最少。
某天,食堂中有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。Input
多组数据。对于每组数据:
第一行为正整数n,表示菜的数量。n<=1000。
第二行包括n个正整数,表示每种菜的价格。价格不超过50。
第三行包括一个正整数m,表示卡上的余额。m<=1000。
n=0表示数据结束。Output
对于每组输入,输出一行,包含一个整数,表示卡上可能的最小余额。
Sample Input
1 50 5 10 1 2 3 2 1 1 2 3 2 1 50 0
Sample Output
-45 32
题解: 如果拥有的钱小于5,输出钱数即可!如果大于5,先把最贵的菜挑出来并把钱-5。之后进行 0 1背包求解
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <algorithm>
using namespace std;
struct node
{
int v;
int w;
} vec[1010];
//int vec[10010];//用STL中的vector时间太长,原因可能是会多次访问vector中的值
int dp[1010];
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
bool cmp(node a,node b)
{
return a.v<b.v;
}
int main()
{
int n;
while ( scanf("%d",&n)!=EOF&&n!=0)
{
memset(dp,0,sizeof(dp));
for(int i=0; i<n; i++)
{
scanf("%d",&vec[i].v);
vec[i].w=vec[i].v;
}
sort(vec,vec+n,cmp);
int maxs=vec[n-1].w;
int m;
scanf("%d",&m);
if(m<5)
{
printf("%d\n",m);
continue;
}
else
{
for(int i=0; i<n-1; i++)
for(int j=m-5; j>=vec[i].v; j--)
dp[j]=max(dp[j],dp[j-vec[i].v]+vec[i].w);
printf("%d\n",m-dp[m-5]-maxs);
}
}
return 0;
}
完全背包
寒冰王座 HDU - 1248
不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票(记住,只有一张钞票),为了防止自己在战斗中频繁的死掉,他决定给自己买一些道具,于是他来到了地精商店前.
死亡骑士:"我要买道具!"
地精商人:"我们这里有三种道具,血瓶150块一个,魔法药200块一个,无敌药水350块一个."
死亡骑士:"好的,给我一个血瓶."
说完他掏出那张N元的大钞递给地精商人.
地精商人:"我忘了提醒你了,我们这里没有找客人钱的习惯的,多的钱我们都当小费收了的,嘿嘿."
死亡骑士:"......"
死亡骑士想,与其把钱当小费送个他还不如自己多买一点道具,反正以后都要买的,早点买了放在家里也好,但是要尽量少让他赚小费.
现在死亡骑士希望你能帮他计算一下,最少他要给地精商人多少小费.Input
输入数据的第一行是一个整数T(1<=T<=100),代表测试数据的数量.然后是T行测试数据,每个测试数据只包含一个正整数N(1<=N<=10000),N代表死亡骑士手中钞票的面值.
注意:地精商店只有题中描述的三种道具.Output
对于每组测试数据,请你输出死亡骑士最少要浪费多少钱给地精商人作为小费.
Sample Input
2 900 250
Sample Output
0 50
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <algorithm>
using namespace std;
//struct node
//{
// int v;
// int w;
//} vec[10010];
int w[3]={150,200,300};
int v[3]={150,200,300};
//int vec[10010];//用STL中的vector时间太长,原因可能是会多次访问vector中的值
int dp[10010];
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
memset(dp,0,sizeof(dp));
int m;
scanf("%d",&m);
for(int i=0; i<3; i++)
for(int j=v[i]; j<=m; j++)
dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
printf("%d\n",m-dp[m]);
}
return 0;
}
多重背包求方案数
问题 K: Transport Ship
时间限制: 1 Sec 内存限制: 128 MB题目描述
There are N different kinds of transport ships on the port. The i^th kind of ship can carry the weight of V[i] and the number of the ith kind of ship is 2C[i]-1. How many different schemes there are if you want to use these ships to transport cargo with a total weight of S? It is required that each ship must be full-filled. Two schemes are considered to be the same if they use the same kinds of ships and the same number for each kind.
输入
The first line contains an integer T(1≤T≤20), which is the number of test cases.
For each test case:
The first line contains two integers: N(1≤N≤20), Q(1≤Q≤10000), representing the number of kinds of ships and the number of queries.
For the next N lines, each line contains two integers: V[i] (1≤V[i]≤20), C[i] (1≤C[i]≤20), representing the weight the i^th kind of ship can carry, and the number of the i^th kind of ship is 2C[i]-1.
For the next Q lines, each line contains a single integer: S (1≤S≤10000), representing the queried weight.输出
For each query, output one line containing a single integer which represents the number of schemes for arranging ships. Since the answer may be very large, output the answer modulo 1000000007.
样例输入
复制样例数据1
1 2
2 1
1
2
样例输出0
1
题目描述:有T组数据,有n条船,q个询问,接下来n行是每条船能装多少重量w和数量c( 2^c-1)下边q行询问的货物重量,问有多少种方案去装货物,每条船必需装满;
注意是所有方案,不是最大价值的方案
#include <bits/stdc++.h>
using namespace std;
int vec[10010];//用STL中的vector时间太长,原因可能是会多次访问vector中的值
int dp[10010],g[10010];
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
int n,mu;
int p=0;
scanf("%d%d",&n,&mu);
for(int i=0; i<n; i++)
{
int a,b;
scanf("%d%d",&a,&b);
b=(1<<b)-1;
for(int k=1; k<=b; k=k*2)
{
b-=k;
vec[p++]=a*k;
//vec.push_back(a*k);
}
if(b>0)
// vec.push_back(a*b);
vec[p++]=a*b;
}
memset(dp,0,sizeof(dp));
dp[0]=1;
for(int j=0; j<p; j++)
for(int k=10000; k>=vec[j]; k--)
{
if(dp[k-vec[j]]>0)
dp[k]+=dp[k-vec[j]];
if(dp[k]>mod)
dp[k]-=mod;
}
for(int i=0; i<mu; i++)
{
int m;
scanf("%d",&m);
printf("%d\n",dp[m]);
}
}
return 0;
}
两个背包
问题 K: PACKING
时间限制: 1 Sec 内存限制: 128 MB
题目描述
It was bound to happen. Modernisation has reached the North Pole. Faced with escalating costs for feeding Santa Claus and the reindeer, and serious difficulties with security, NP Management has decided to do away with the traditional sleigh and adopt delivery by drone (magic, superfast drone).
Lack of investment capital means that the new system will start small, and hopefully grow in the years to come. For the first test run in 2017 there will be only two drones and they will have limited carrying capacity. PR is, of course, all important. There will be disappointment, and NP Management has decided to focus on delivering only the most expensive toys to the richest children, so as to focus the worst of the disappointment on those who have the greatest experience of coping (the poor).
Choosing the presents to deliver is your problem. You are being asked to develop an algorithm to select the cargo to deliver, given weight limits for each of the drones and a list of candidate presents with weights and values. Your goal is to maximise the value of gifts delivered.输入
Input will consist of a series of problems. The first line of the input holds a single integer P being the number of problems. Then for each problem there will be three lines of input. The first line holds three integers: N (1 <= N <= 100) being the number of candidate presents; W1 and W2 (1 <= W1, W2 <= 1000) being the weight limits of the two drones respectively. The second line holds N integers (1 <= wi <= 100) being the weights of each of the candidate presents and the third line holds N integers (1 <= vi <= 100) being the values of the presents (in thousand dollar units). All lines are formatted with single spaces between numbers and no leading or trailing spaces.
输出
For each problem your program should output one line with the text “Problem “ and the number of the problem (counting from 1) followed by a colon, a space and the total value of presents shipped by the drone pair.
样例输入
复制样例数据2 4 9 4 3 4 5 6 5 7 9 10 6 9 11 3 4 5 6 3 4 2 3 4 5 3 3样例输出
Problem 1: 22 Problem 2: 16
题目大意:有n个物品,有两架飞机,每个飞机的载重是w1,w2。下边两行代表的是每个包裹的重量和价值,问怎样装才能让价值最大。
#pragma GCC optimize(3) //(关键)//提高程序运行速度,但是有时候不稳定.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <algorithm>
using namespace std;
#pragma GCC optimize(3) //(关键)
struct node
{
int v;
int w;
} vec[10010];
//int vec[10010];//用STL中的vector时间太长,原因可能是会多次访问vector中的值
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
int dp[1005][1005];
int main()
{
int t;
scanf("%d",&t);
int T=1;
while(t--)
{
memset(dp,0,sizeof(dp));
int n,w1,w2;
scanf("%d%d%d",&n,&w1,&w2);
for(int i=1; i<=n; i++)
scanf("%d",&vec[i].w);
for(int i=1; i<=n; i++)
scanf("%d",&vec[i].v);
for(int k=1; k<=n; k++)
for(int i=w1; i>=0; i--)
{
for(int j=w2; j>=0; j--)
{
if(i>=vec[k].w)
dp[i][j]=dp[i-vec[k].w][j]+vec[k].v>dp[i][j]?dp[i-vec[k].w][j]+vec[k].v:dp[i][j];
if(j>=vec[k].w)
dp[i][j]=dp[i][j-vec[k].w]+vec[k].v>dp[i][j]?dp[i][j-vec[k].w]+vec[k].v:dp[i][j];
}
}
printf("Problem %d: %d\n",T++,dp[w1][w2]);
}
return 0;
}