小乐乐的化妆品0.1背包 |
||||||
|
||||||
Description |
||||||
小乐乐辛苦的走到了山脚,却发现山脚多了一个藏宝洞。小乐乐走了进去,无数的化妆品啊!小乐乐眼睛都花了,于是她打开书包开始装。不同的化妆品有不同的价值和不同的大小,每种化妆品只有一个。但是小乐乐的书包很小,最多只能放v体积的东西。小乐乐现在很想知道,她最多能带走多少价值的东西呢? |
||||||
Input |
||||||
第一行输入物品数量n(1<n<100) 和 书包体积 v(0<=v<1000) |
||||||
Output |
||||||
输出小乐乐能带走的最大的价值 |
||||||
Sample Input |
||||||
5 10 |
||||||
Sample Output |
||||||
10 |
#include<stdio.h>
#include<string.h>
struct huazhuangpin
{
int c,val;
}a[10000];
int dp[100001];
int main()
{
int n,v;
while(~scanf("%d%d",&n,&v))
{
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
{
scanf("%d%d",&a[i].c,&a[i].val);
}
/*0-1背包的动态规划思想:令j=最大容量,只要当前j能够装下当前物品 就装下试一试.直到装不下为止.*/
for(int i=0;i<n;i++)
{
for(int j=v;j>=a[i].c;j--) //j=max(v);只要是能装下 就一步一步试.
{
if(dp[j-a[i].c]+a[i].val>dp[j])
{
dp[j]=dp[j-a[i].c]+a[i].val;
}
}
}
printf("%d\n",dp[v]);
}
}
Warcraft III完全背包 |
||||||
|
||||||
Description |
||||||
dccmx likes playing Warcraft III. Now, he is teaching his girlfriend to play it. In Warcraft III, there are many kinds of units. Every unit costs some gold and lumber. Different units have different attack value. Now question comes. Given some amount of gold and a list of types of units, how to arrange your units to maximize the attack value of your units. Assume you have infinite lumbers. |
||||||
Input |
||||||
Line 1 contains an integer T: the number of test cases. Next T blocks, each starts with two integers: G and U, represents the amount of gold and number of unit type. Next U lines, each contains two integers: the attack value of a type of unit and the cost. |
||||||
Output |
||||||
For each test case, output the maximum total attack value in one line. |
||||||
Sample Input |
||||||
2 100 1 20 10 300 4 100 60 250 120 120 100 35 20 |
||||||
Sample Output |
||||||
200 605 |
||||||
Author |
||||||
dccmx |
#include<stdio.h>
#include<string.h>
struct compeletepack
{
int val,w;
}a[10000];
int dp[1000001];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(dp,0,sizeof(dp));
int g,n;
scanf("%d%d",&g,&n);
for(int i=0;i<n;i++)
{
scanf("%d%d",&a[i].val,&a[i].w);
}
/*完全背包思想:int j为当前物品的重量 如果重量还够 就装着试一试.直到不能装了为止.*/
for(int i=0;i<n;i++)
{
for(int j=a[i].w;j<=g;j++)
{
if(dp[j-a[i].w]+a[i].val>dp[j])//如果当前处理大于没处理的 就进行更换最优解.
{
dp[j]=dp[j-a[i].w]+a[i].val;
}
}
}
printf("%d\n",dp[g]);
}
}
悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包)
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 20171 Accepted Submission(s): 8505
Problem Description
急!灾区的食物依然短缺!
为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品,其价格不等,并且只能整袋购买。
请问:你用有限的资金最多能采购多少公斤粮食呢?
后记:
人生是一个充满了变数的生命过程,天灾、人祸、病痛是我们生命历程中不可预知的威胁。
月有阴晴圆缺,人有旦夕祸福,未来对于我们而言是一个未知数。那么,我们要做的就应该是珍惜现在,感恩生活——
感谢父母,他们给予我们生命,抚养我们成人;
感谢老师,他们授给我们知识,教我们做人
感谢朋友,他们让我们感受到世界的温暖;
感谢对手,他们令我们不断进取、努力。
同样,我们也要感谢痛苦与艰辛带给我们的财富~
Input
输入数据首先包含一个正整数C,表示有C组测试用例,每组测试用例的第一行是两个整数n和m(1<=n<=100, 1<=m<=100),分别表示经费的金额和大米的种类,然后是m行数据,每行包含3个数p,h和c(1<=p<=20,1<=h<=200,1<=c<=20),分别表示每袋的价格、每袋的重量以及对应种类大米的袋数。
Output
对于每组测试数据,请输出能够购买大米的最多重量,你可以假设经费买不光所有的大米,并且经费你可以不用完。每个实例的输出占一行。
Sample Input
1
8 2
2 100 4
4 100 2
Sample Output
400
/*多重背包的思路就是把多重的重字去掉 换成01背包就行咯~~~~*/
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
struct dami
{
int c,val;
}a[100000];
int dp[101010];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(dp,0,sizeof(dp));
int v,n;
scanf("%d%d",&v,&n);
int zhongliang,jiazhi,u;
int cont=0;
for(int i=0;i<n;i++)
{
scanf("%d%d%d",&zhongliang,&jiazhi,&u);
for(int j=0;j<u;j++)
{
a[cont].c=zhongliang;
a[cont].val=jiazhi;
cont++;
}
}
////////////////////////
for(int i=0;i<cont;i++)
{
for(int j=v;j>=a[i].c;j--)
{
if(dp[j-a[i].c]+a[i].val>dp[j])
{
dp[j]=dp[j-a[i].c]+a[i].val;
}
}
}
printf("%d\n",dp[v]);
}
}
寒冰王座
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 13568 Accepted Submission(s): 6897
Problem Description
不死族的巫妖王发工资拉,死亡骑士拿到一张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<stdio.h>
#include<cstring>
#include<iostream>
using namespace std;
int dp[10005];
int main()
{
int t,n,i,j;
int c[3]={150,200,350};
int w[3]={150,200,350};
scanf("%d",&t);
while(t--)
{
memset(dp,0,sizeof(dp));
scanf("%d",&n);
/////这个题让我领悟了好多好多东西 完全背包就是 能装的就给我造死里装 能咋装 就咋装
for(i=0;i<3;i++)//每个种类(物品都要扫一遍)
{
for(j=1;j<=n;j++)//int一个j为当前物品的消耗.让dp造死里装.
{
if(j>=c[i])
dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
}
}
printf("%d\n",n-dp[n]);
}
}
Piggy-Bank(完全背包.)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 16790 Accepted Submission(s): 8475
Problem Description
Before ACM can do anything, a budget must be prepared and the necessary financial support obtained. The main income for this action comes from Irreversibly Bound Money (IBM). The idea behind is simple. Whenever some ACM member has any small money, he takes all the coins and throws them into a piggy-bank. You know that this process is irreversible, the coins cannot be removed without breaking the pig. After a sufficiently long time, there should be enough cash in the piggy-bank to pay everything that needs to be paid.
But there is a big problem with piggy-banks. It is not possible to determine how much money is inside. So we might break the pig into pieces only to find out that there is not enough money. Clearly, we want to avoid this unpleasant situation. The only possibility is to weigh the piggy-bank and try to guess how many coins are inside. Assume that we are able to determine the weight of the pig exactly and that we know the weights of all coins of a given currency. Then there is some minimum amount of money in the piggy-bank that we can guarantee. Your task is to find out this worst case and determine the minimum amount of cash inside the piggy-bank. We need your help. No more prematurely broken pigs!
Input
The input consists of T test cases. The number of them (T) is given on the first line of the input file. Each test case begins with a line containing two integers E and F. They indicate the weight of an empty pig and of the pig filled with coins. Both weights are given in grams. No pig will weigh more than 10 kg, that means 1 <= E <= F <= 10000. On the second line of each test case, there is an integer number N (1 <= N <= 500) that gives the number of various coins used in the given currency. Following this are exactly N lines, each specifying one coin type. These lines contain two integers each, Pand W (1 <= P <= 50000, 1 <= W <=10000). P is the value of the coin in monetary units, W is it's weight in grams.
Output
Print exactly one line of output for each test case. The line must contain the sentence "The minimum amount of money in the piggy-bank is X." where X is the minimum amount of money that can be achieved using coins with the given total weight. If the weight cannot be reached exactly, print a line "This is impossible.".
Sample Input
3
10 110
2
1 1
30 50
10 110
2
1 1
50 30
1 6
2
10 3
20 4
Sample Output
The minimum amount of money in the piggy-bank is 60.
The minimum amount of money in the piggy-bank is 100.
This is impossible.
就是有一个存钱罐,比不知道里面有多少钱,但是我们知道(就是 输入)T组测试数据
E 空的存钱罐的质量, F 存钱罐装满钱的重量,
接着输入 N 里面硬币的种类,下面N行
P 硬币的价值, W 硬币的质量
你的任务是求出来存钱罐里面最少多少钱 样例1:
10 110
2
1 1
30 50
里面的硬币是 2个价值30,重量为50的硬币的时候,最少,故宗价值最少60.
#include<stdio.h>
#include<string.h>
int dp[101010];
struct coin
{
int val,w;
}s[1000000];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
dp[0]=0;//另外一定要设dp[0]=0;要不然就废了0.0
int a,b,temp;
scanf("%d%d",&a,&b);
if(a>b)//防止a>b 使得b-a为负数 就错咯~~~~
{
temp=a;
a=b;
b=a;
}
for(int i=1;i<10000;i++)
{
dp[i]=100000000;//求最小背包值的方式在这里 要定义个特别特别大的数.
}
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d%d",&s[i].val,&s[i].w);
}
for(int i=0;i<n;i++)
{
for(int j=s[i].w;j<=b-a;j++)//令j=要消耗的东西.只要能继续装 就造死了装.
{
if(dp[j-s[i].w]+s[i].val<dp[j])//供给给他们让他们小于这么大个数然后动态的去更新最小值哦.
{
dp[j]=dp[j-s[i].w]+s[i].val;
}
}
}
if(dp[b-a]==100000000)//如果超出了范围就没有更新这个值 所以就是输出不可能.
{printf("This is impossible.\n");continue;}
printf("The minimum amount of money in the piggy-bank is %d.\n",dp[b-a]);
}
}
Bone Collector(0-1背包问题)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 41490 Accepted Submission(s): 17266
Problem Description
Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’s , cow’s , also he went to the grave …
The bone collector had a big bag with a volume of V ,and along his trip of collecting there are a lot of bones , obviously , different bone has different value and different volume, now given the each bone’s value along his trip , can you calculate out the maximum of the total value the bone collector can get ?
Input
The first line contain a integer T , the number of cases.
Followed by T cases , each case three lines , the first line contain two integer N , V, (N <= 1000 , V <= 1000 )representing the number of bones and the volume of his bag. And the second line contain N integers representing the value of each bone. The third line contain N integers representing the volume of each bone.
Output
One integer per line representing the maximum of the total value (this number will be less than 231).
Sample Input
1
5 10
1 2 3 4 5
5 4 3 2 1
Sample Output
14
#include<stdio.h>
#include<string.h>
int val[1000];
int c[1000];
int a[1010][1010];
int dp[1010];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(dp,0,sizeof(dp));
int n,v;
scanf("%d%d",&n,&v);
for(int i=0;i<n;i++)
{
scanf("%d",&val[i]);
}
for(int i=0;i<n;i++)
{
scanf("%d",&c[i]);
}
for(int i=0;i<n;i++)
{
for(int j=v;j>=c[i];j--)
{
if(dp[j-c[i]]+val[i]>dp[j])
{
dp[j]=dp[j-c[i]]+val[i];
}
}
}
printf("%d\n",dp[v]);
}
}
Big Event in HDU
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 30322 Accepted Submission(s): 10652
Problem Description
Nowadays, we all know that Computer College is the biggest department in HDU. But, maybe you don't know that Computer College had ever been split into Computer College and Software College in 2002.
The splitting is absolutely a big event in HDU! At the same time, it is a trouble thing too. All facilities must go halves. First, all facilities are assessed, and two facilities are thought to be same if they have the same value. It is assumed that there is N (0<N<1000) kinds of facilities (different value, different kinds).
Input
Input contains multiple test cases. Each test case starts with a number N (0 < N <= 50 -- the total number of different facilities). The next N lines contain an integer V (0<V<=50 --value of facility) and an integer M (0<M<=100 --corresponding number of the facilities) each. You can assume that all V are different.
A test case starting with a negative integer terminates input and this test case is not to be processed.
Output
For each case, print one line containing two integers A and B which denote the value of Computer College and Software College will get respectively. A and B should be as equal as possible. At the same time, you should guarantee that A is not less than B.
Sample Input
2
10 1
20 1
3
10 1
20 2
30 1
-1
Sample Output
20 10
40 40
/*把价值当做容积也是6的飞起.如果当前物品ans能够完全容进去 就01背直接背走
如果不能就用完全背包一点一点背.*/
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int dp[100000],sum,ans;
struct wupin
{
int v,m;
}a[100000];
void one(int x)
{
for(int j=1;j<=a[x].m;j++)
{
for(int j=ans;j>=a[x].v;j--)
{
dp[j]=max(dp[j],dp[j-a[x].v]+a[x].v);
}
}
}
void full(int x)
{
for(int i=a[x].v;i<=ans;i++)
{
dp[i]=max(dp[i],dp[i-a[x].v]+a[x].v);
}
}
int main()
{
int i,j,n;
while(scanf("%d",&n)&&(n>0))
{
memset(dp,0,sizeof(dp));
sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].v,&a[i].m);
sum+=a[i].v*a[i].m;
}
ans=sum/2;//把ans当做容积.
for(int i=1;i<=n;i++)
{
if(a[i].v*a[i].m>=ans)
full(i);
else
one(i);
}
printf("%d %d\n",sum-dp[ans],dp[ans]);
}
}
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 10131 Accepted Submission(s): 4803
Problem Description
最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务。久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级。现在的问题是,xhd升掉最后一级还需n的经验值,xhd还留有m的忍耐度,每杀一个怪xhd会得到相应的经验,并减掉相应的忍耐度。当忍耐度降到0或者0以下时,xhd就不会玩这游戏。xhd还说了他最多只杀s只怪。请问他能升掉这最后一级吗?
Input
输入数据有多组,对于每组数据第一行输入n,m,k,s(0 < n,m,k,s < 100)四个正整数。分别表示还需的经验值,保留的忍耐度,怪的种数和最多的杀怪数。接下来输入k行数据。每行数据输入两个正整数a,b(0 < a,b < 20);分别表示杀掉一只这种怪xhd会得到的经验值和会减掉的忍耐度。(每种怪都有无数个)
Output
输出升完这级还能保留的最大忍耐度,如果无法升完这级输出-1。
Sample Input
10 10 1 101 110 10 1 91 19 10 2 101 12 2
Sample Output
0-11
首先要谈一下刚刚接触二重完全背包的感受.我把限制次数当做一个坎.如果能用一重完全背包装进去的东西s--来进行判断 如果s>=0就能输出结果 。但是本渣还是想的太少啊.too yong to simple.
二重完全背包比一重完全背包多的一项就是限制了次数.
由以下三组dp数据可得出结论 dp算的还是与消耗的相反的东西 就是经验值咯~.
这个题还是相对比较难的.如果仅仅是求输出最优价值来说(限制次数是理所当然的).题目解还是比较容易理解的.但他要输出的是剩余的最大忍耐力.每一次我们求的都是(每一次)
消耗了忍耐力的最优经验值解.
(每一次都消耗了相应需要消耗的经验值 所以在输出的时候是用的m-i);
10 10 1 10
1 1
0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1
0 1 2 2 2 2 2 2 2 2 2
0 1 2 3 3 3 3 3 3 3 3
0 1 2 3 4 4 4 4 4 4 4
0 1 2 3 4 5 5 5 5 5 5
0 1 2 3 4 5 6 6 6 6 6
0 1 2 3 4 5 6 7 7 7 7
0 1 2 3 4 5 6 7 8 8 8
0 1 2 3 4 5 6 7 8 9 9
0 1 2 3 4 5 6 7 8 9 10
10 10 1 9
1 1
0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1
0 1 2 2 2 2 2 2 2 2 2
0 1 2 3 3 3 3 3 3 3 3
0 1 2 3 4 4 4 4 4 4 4
0 1 2 3 4 5 5 5 5 5 5
0 1 2 3 4 5 6 6 6 6 6
0 1 2 3 4 5 6 7 7 7 7
0 1 2 3 4 5 6 7 8 8 8
0 1 2 3 4 5 6 7 8 9 9
10 10 1 9
1 1
0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 1 1
0 1 2 2 2 2 2 2 2 2 2
0 1 2 3 3 3 3 3 3 3 3
0 1 2 3 4 4 4 4 4 4 4
0 1 2 3 4 5 5 5 5 5 5
0 1 2 3 4 5 6 6 6 6 6
0 1 2 3 4 5 6 7 7 7 7
0 1 2 3 4 5 6 7 8 8 8
0 1 2 3 4 5 6 7 8 9 9
10 10 2 10
2 1
2 2
0 0 0 0 0 0 0 0 0 0 0
0 2 2 2 2 2 2 2 2 2 2
0 2 4 4 4 4 4 4 4 4 4
0 2 4 6 6 6 6 6 6 6 6
0 2 4 6 8 8 8 8 8 8 8
0 2 4 6 8 10 10 10 10 10 10
0 2 4 6 8 10 12 12 12 12 12
0 2 4 6 8 10 12 14 14 14 14
0 2 4 6 8 10 12 14 16 16 16
0 2 4 6 8 10 12 14 16 18 18
0 2 4 6 8 10 12 14 16 18 20
以上是三组dp的后台数据.
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
struct guaiwu
{
int val,endure;
}a[10000];
int dp[1010][1010];
int main()
{
int n,m,k,s;
while(~scanf("%d%d%d%d",&n,&m,&k,&s))
{
memset(dp,0,sizeof(dp));
for(int i=1;i<=k;i++)
{
scanf("%d%d",&a[i].val,&a[i].endure);
}
for(int i=1;i<=k;i++)
{
for(int xz=1;xz<=s;xz++)
{
for(int j=a[i].endure;j<=m;j++)
{
dp[xz][j]=max(dp[xz][j],dp[xz-1][j-a[i].endure]+a[i].val);//再一次强调当前处理.xz-1处当注意.
}
}
}
int i;
for(i=0;i<=m;i++)//不能超过忍耐力的次数.
{
if(dp[s][i]>=n)break;//只判断最优解的一行.
}//如果能够升级 就break 因为升级了就够了 不需要再消耗忍耐力了.
if(dp[s][i]<n)printf("-1\n");
else printf("%d\n",m-i);//因为消耗的就是忍耐力 所以判断次数就能判断出剩余忍耐力
.
}
}
PROBLEM-FOUR |
||||||
|
||||||
Description |
||||||
给定n种物品和一个背包。物品i的重量是wi,其价值为vi,背包所能装载的最大为C。应如何选择装入背包的物品,使得装入背包中物品的总价值最大。 |
||||||
Input |
||||||
有多组输入数据。 |
||||||
Output |
||||||
每组数据输出一个浮点数代表最大的总价值,(保留2位小数)每个输出占单独一行。 |
||||||
Sample Input |
||||||
3 10 |
||||||
Sample Output |
||||||
40.00 |
||||||
Hint |
||||||
注意答案是浮点数。 |
||||||
Source |
||||||
新生练习赛(2013.11.10) |
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct node
{
int w,val;
double xingjiabi;
}a[5050];
int cmp(node x,node y)
{
return x.xingjiabi > y.xingjiabi;
}
int main()
{
int n,c;
while(~scanf("%d%d",&n,&c))
{
for(int i=0;i<n;i++)
{
scanf("%d%d",&a[i].w,&a[i].val);
a[i].xingjiabi=1.0*a[i].val/a[i].w;
}
sort(a,a+n,cmp);
int j=c;
double sum=0;
for(int i=0;i<n;i++)
{
if(j>=a[i].w)
{
sum+=a[i].val;
j-=a[i].w;
}
else
{
sum+=j*1.0/a[i].w*a[i].val;
j=0;
}
if(j==0)break;
}
printf("%.2lf\n",sum);
}
}