NYOJ-289-苹果
苹果
时间限制:3000 ms | 内存限制:65535 KB
难度:3
描述
ctest有n个苹果,要将它放入容量为v的背包。给出第i个苹果的大小和价钱,求出能放入背包的苹果的总价钱最大值。
输入
有多组测试数据,每组测试数据第一行为2个正整数,分别代表苹果的个数n和背包的容量v,n、v同时为0时结束测试,此时不输出。接下来的n行,每行2个正整数,用空格隔开,分别代表苹果的大小c和价钱w。所有输入数字的范围大于等于0,小于等于1000。
输出
对每组测试数据输出一个整数,代表能放入背包的苹果的总价值。
样例输入
3 3
1 1
2 1
3 1
0 0
样例输出
2
由题不难得到这道题是01背包问题(不装满、有限)
代码:
#include <stdio.h>
#include <string.h>
//#include <algorithm>
//using namespace std;//效率低
#define max(a,b) a>b?a:b
int main()
{
int n,v,i,j;
while(~scanf("%d%d",&n,&v),n,v)
{
/* int c[1010],w[1010],sum[1010];
for(i=0;i<n;i++)
{
scanf("%d%d",&c[i],&w[i]);
}
memset(sum,0,sizeof(sum));
for(i=0;i<n;i++)
{
for(j=v;j>=c[i];j--)//j<c[i]说明背包不够放
{
sum[j]=max(sum[j],sum[j-c[i]]+w[i]);// 比较放这个和不放这个的大小
}
}*///提高效率
int c,w,sum[1010];
memset(sum,0,sizeof(sum));
for(i=0;i<n;i++)
{
scanf("%d%d",&c,&w);
for(j=v;j>=c;j--)//j<c[i]说明背包不够放
{
sum[j]=max(sum[j],sum[j-c]+w);// 比较放这个和不放这个的大小
}
}
printf("%d\n",sum[v]);
}
return 0;
}
NYOJ-311-完全背包
时间限制:3000 ms | 内存限制:65535 KB
难度:4
描述
直接说题意,完全背包定义有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的体积是c,价值是w。求解将哪些物品装入背包可使这些物品的体积总和不超过背包容量,且价值总和最大。本题要求是背包恰好装满背包时,求出最大价值总和是多少。如果不能恰好装满背包,输出NO
输入
第一行: N 表示有多少组测试数据(N<7)。
接下来每组测试数据的第一行有两个整数M,V。 M表示物品种类的数目,V表示背包的总容量。(0< M<=2000,0< V<=50000)
接下来的M行每行有两个整数c,w分别表示每种物品的重量和价值(0< c<100000,0< w<100000)
输出
对应每组测试数据输出结果(如果能恰好装满背包,输出装满背包时背包内物品的最大价值总和。 如果不能恰好装满背包,输出NO)
样例输入
2
1 5
2 2
2 5
2 2
5 1
样例输出
NO
1
AC
#include <stdio.h>
#include <string.h>
#define max(a,b) a>b?a:b
int dp[100010];
int main()
{
int n,m,v;//m数目,v背包容量
scanf("%d",&n);
while(n--)
{
int c,w;
int i,j;
memset(dp,-0x3f,sizeof(dp));
dp[0]=0;
scanf("%d%d",&m,&v);
for(i=1;i<=m;i++)
{
scanf("%d%d",&c,&w);
for(j=c;j<=v;j++)
{
dp[j]=max(dp[j],dp[j-c]+w);
}
}
if(dp[v]<0)//这里要判断的是dp[背包总容积]
printf("NO\n");
else
printf("%d\n",dp[v]);
}
return 0;
}
采药
题目描述
辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。” 如果你是辰辰,你能完成这个任务吗?
输入
第一行有两个整数T(1 < = T < = 1000)和M(1 < = M < = 100),用一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。接下来的M行每行包括两个在1到100之间(包括1和100)的整数,分别表示采摘某株草药的时间和这株草药的价值。
输出
输出包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。
样例输入
70 3
71 100
69 1
1 2
样例输出
3
提示
对于30%的数据,M < = 10;对于全部的数据,M < = 100。
代码
#include <stdio.h>
#include <string.h>
#define max(a,b) a>b?a:b
int main()
{
int st,m;
scanf("%d%d",&st,&m);
int i,j,t,value;
int dp[1005]={0};
for(i=1;i<=m;i++)
{
scanf("%d%d",&t,&value);
for(j=st;j>=t;j--)
{
dp[j]=max(dp[j],dp[j-t]+value);
}
}
printf("%d\n",dp[st]);
return 0;
}
1149: 多重部分和问题
时间限制: 1 Sec 内存限制: 128 MB
提交: 160 解决: 88
题目描述
有n中不同大小的数字ai,每种各mi个。判断是否可以从这些数字之中选出若干使他们的大小恰好为K.
限制条件
1<=n<=100
1<=ai,mi<=100000
1<=k<=100000
输入
多组数据。
第一行n。第二行不同的数字ai.第三行对应数字拥有的个数
输出
能挑选若干恰好和为K则输出“Yes”,反之输出“No”.
样例输入
1
3
3 5 8
3 2 2
17
样例输出
Yes
可以这样想:把mi个数字ai拆开,当做01背包问题来做就简单了很多
代码:
#include <stdio.h>
#include <string.h>
#define max(a,b) a>b?a:b
int a[100005],m[100005],dp[100005];
int main()
{
int t,n,k,i,j;
scanf("%d",&t);
while(t--)
{
memset(dp,-0x3f,sizeof(dp));
dp[0]=0;//初始化
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<=n;i++)
scanf("%d",&m[i]);
scanf("%d",&k);//输入
for(i=1;i<=n;i++)
{
while(m[i]--)//m[i]是a[i]的个数
{
for(j=k;j>=a[i];j--)
{
dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
}
}
if(dp[k]==k)//如果相加得到k就退出 输出yes
{
printf("Yes\n");
break;
}
}
if(dp[k]<0)
printf("No\n");
}
return 0;
}
HDU-1712-ACboy needs your help
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6346 Accepted Submission(s): 3504
Problem Description
ACboy has N courses this term, and he plans to spend at most M days on study.Of course,the profit he will gain from different course depending on the days he spend on it.How to arrange the M days for the N courses to maximize the profit?
Input
The input consists of multiple data sets. A data set starts with a line containing two positive integers N and M, N is the number of courses, M is the days ACboy has.
Next follow a matrix A[i][j], (1<=i<=N<=100,1<=j<=M<=100).A[i][j] indicates if ACboy spend j days on ith course he will get profit of value A[i][j].
N = 0 and M = 0 ends the input.
Output
For each data set, your program should output a line which contains the number of the max profit ACboy will gain.
Sample Input
2 2
1 2
1 3
2 2
2 1
2 1
2 3
3 2 1
3 2 1
0 0
Sample Output
3
4
6
题意:
一个学生用M天的时间复习N门课程,每门课程花费不同的天数,有不同的收获。问如何安排这M天,使得收获最大。
思路:
可以将每一门课看成一个分组,每门课不同天数的选择看成是分组的物品(显然只能有一个选择),
物品的费用即为花费的天数,物品的价值为题中给出的收获。该题中背包容量最大为M。
设dp[x]为前i组物品,在背包容量为x(即费用为x)时的最大价值。则将i从1到N进行过历遍后(第一重循环),dp[m]即为所求。
AC
#include <stdio.h>
#include <string.h>
#define max(a,b) a>b?a:b
int dp[105];
int main()
{
int n,m;
int i,j,k,q;
int a[105][105];
while(scanf("%d%d",&n,&m),n,m)// n节课,m是有的天数
{
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)//课程
{
for(j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);//a[i][j] i课花费j天的收获
}
for(k=m;k>=1;k--)//倒着放
{
for(q=1;q<=k;q++){//q<=k最多不能多于给的最多天数
dp[k]=max(dp[k],dp[k-q]+a[i][q]);
}
}
}
printf("%d\n",dp[m]);
}
return 0;
}
HDU-2191-悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
##
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
题意:
为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金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
对于每组测试数据,请输出能够购买大米的最多重量,你可以假设经费买不光所有的大米,并且经费你可以不用完。每个实例的输出占一行。
AC:
#include <stdio.h>
#include <string.h>
#define max(a,b) a>b?a:b
int main()
{
int t,n,m;
int i,j;
int dp[105];
scanf("%d",&t);
while(t--)
{
int p,h,c;//p每袋价值,h每袋重量,c袋数
scanf("%d%d",&n,&m);//n元,m种
memset(dp,0,sizeof(dp));//初始化放for外面
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&p,&h,&c);
while(c--)
{
for(j=n;j>=p;j--)
{
dp[j]=max(dp[j],dp[j-p]+h);
}
}
}
printf("%d\n",dp[n]);
}
return 0;
}
收获:这类题可以通过观察提议判断题目中要求 物品无限、有限、背包装满、不装满,然后根据这些条件来做题。
其中物品无限:
for(i=1;i<=n;i++)
{
for(j=a[i];j<sweight/*总重*/;j++)//正着放
dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
}
物品有限:
for(i=1;i<=n;i++)
{
for(j=sweight/*总重*/;j>=a[i];j--)//倒着放
dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
}
装满:
初始化:
memset(dp,-0x3f,sizeof(dp));
dp[0]=0;
不装满:
memset(dp,0,sizeof(dp));
以上。