背包问题经典实现方法
来源:互联网 发布:mysql explain 详解 编辑:程序博客网 时间:2024/06/06 12:56
背包问题里“背包”的英文是 knopsack ,其基本问题就假设有一个限定重量的背包,若干一定重量的物品,每个物品都有各自的价值, 现在要尽可能的向背包里装入若干物品,使得背包中物品价值之和最大。这个问题在密码学上有重要的应用,有很多先进的算法,可惜我不懂……不过没关系,因为至少我们还有DP,可以使用空间复杂度O(n)时间复杂度O(n^2)的算法圆满实现该算法。
约定:背包的重量为c,物品重量为n,物品的重量为w[i],价值为v[i]。
基本的DP:
假设ks[i,j]表示在前i件物品中选取若干件(每件可以选取多次),使得包内装总重量为j时能得到的最大价值。则:
ks[0,0] = 0
ks[i,j] = max { ks[i-1,j-w[i]*k]+v[i]*k | 1<= k <= c/w[i] }
*如果每种物品只能拿一次(不可重复背包问题),去掉k。
真正实现的时候,由于考察第i种物品的时候只需要i-1有关的信息,所以只需要一个一维数组来储存。
来看一个(我认为)经典的DP程序:
(这段程序大概是这么来的:Somewhere(也许是Maigo的大脑)-->Maigo写的USACO标程-->MiniDragonXG同学消化+改编-->这里)
for(i=0;i<=c;i++) ks[i]=-1;
ks[0]=0;
for(i=1;i<=n;i++)...{
for(j=w[i];j<=c;j++) //改为for(j=c;j>=w[i];j--) 就能求不可重复背包问题
if(ks[j-w[i]]>=0 && ks[j]<ks[j-w[i]]+v[i])
}
max=-1;
for(i=0;i<=s;i++) if(ks[i]>max) max=ks[i];
//max即为最大价值
这一段程序融合了背包状态存在性问题和可重复/不可重复问题,可谓做基本背包问题的居家良药啊-_-b
搜挂了3道有数据的题(贴在下面),一举拿下(也贴在下面),你也试试?(什么,你BS我……那我也BS你……靠)
USACO Training Page Section 3.1 Score Inflation
Score Inflation
The more points students score in our contests, the happier we here at the USACO are. We try to design our contests so that people can score as many points as possible, and would like your assistance.
We have several categories from which problems can be chosen, where a "category" is an unlimited set of contest problems which all require the same amount of time to solve and deserve the same number of points for a correct solution. Your task is write a program which tells the USACO staff how many problems from each category to include in a contest so as to maximize the total number of points in the chosen problems while keeping the total solution time within the length of the contest.
The input includes the length of the contest, M (1 <= M <= 10,000) (don't worry, you won't have to compete in the longer contests until training camp) and N, the number of problem categories, where 1 <= N <= 10,000.
Each of the subsequent N lines contains two integers describing a category: the first integer tells the number of points a problem from that category is worth (1 <= points <= 10000); the second tells the number of minutes a problem from that category takes to solve (1 <= minutes <= 10000).
Your program should determine the number of problems we should take from each category to make the highest-scoring contest solvable within the length of the contest. Remember, the number from any category can be any nonnegative integer (0, one, or many). Calculate the maximum number of possible points.
PROGRAM NAME: inflate
INPUT FORMAT
Line 1: M, N -- contest minutes and number of problem classes
Lines 2-N+1: Two integers: the points and minutes for each class
SAMPLE INPUT (file inflate.in)
300 4
100 60
250 120
120 100
35 20
OUTPUT FORMAT
A single line with the maximum number of points possible given the constraints.
SAMPLE OUTPUT (file inflate.out)
605
(Take two problems from #2 and three from #4.)
#include<stdio.h>
int main(void)
...{
FILE *fin=fopen("inflate.in","r");
FILE *fout=fopen("inflate.out","w");
long n,w,v,c;
long ks[10001];
int i,j;
fscanf(fin,"%d %d ",&c,&n);
for(i=0;i<=c;i++) ks[i]=-1;
ks[0]=0;
for(i=1;i<=n;i++)...{
fscanf(fin,"%d %d ",&v,&w);
for(j=w;j<=c;j++)
if(ks[j-w]>=0 && ks[j]<ks[j-w]+v) ks[j]=ks[j-w]+v;
}
for(i=c,j=-1;i>=0;i--) if(ks[i]>j)j=ks[i];
fprintf(fout,"%d ",j);
return 0;
}
NOIP2001普及组 装箱问题
描述 Description 有一个箱子容量为v(正整数,o≤v≤20000),同时有n个物品(o≤n≤30),每个物品有一个体积 (正整数)。要求从 n 个物品中,任取若千个装入箱内,使箱子的剩余空间为最小。
输入格式 Input Format 第一行,一个整数,表示箱子容量;
第二行,一个整数,表示有n个物品;
接下来n行,分别表示这n个物品的各自体积。 输出格式 Output Format 一个整数,表示箱子剩余空间。
#include<stdbool.h>
int main(void)
...{
int n,v;
int i,j;
int ans;
bool ks[20001];
int w[31];
bool found=false;
scanf("%d %d ",&v,&n);
for(i=1;i<=n;i++) scanf("%d ",&w[i]);
memset((void*)ks,0,sizeof(ks));
ks[0]=true;
for(i=1;i<=n;i++)
for(j=v;j>=w[i];j--)
ks[j]=ks[j] || ks[j-w[i]];
for(ans=v;!ks[ans];ans--);
printf("%d ",v-ans);
return 0;
}
NOIP2006 OIBH第三次模拟赛普及组Problem 3 : maxsum 最大约数和
Problem 3 : maxsum 最大约数和
源文件名:maxsum.(pas/c/cpp)
输入文件:maxsum.in
输出文件:maxsum.out
时间限制:1秒
空间限制:64M
问题描述
选取和不超过S的若干个不同的正整数,使得所有数的约数(不含它本身)之和最大。
输入格式
输入一个正整数S。
输出格式
输出最大的约数之和。
样例输入
11
样例输出
9
样例说明
取数字4和6,可以得到最大值(1 + 2) + (1 + 2 + 3) = 9。
数据规模...
#include<math.h>
int main(void)
...{
int ks[1001];
int s,i,j,v;
FILE *fin=stdin;
fscanf(fin,"%d ",&s);
for(i=0;i<=s;i++) ks[i]=-1;
ks[0]=0;
for(i=1;i<=s;i++)...{
v=value(i);
for(j=i;j<=s;j++)
if(ks[j-i]>=0 && ks[j]<ks[j-i]+v) ks[j]=ks[j-i]+v;
}
v=-1;
for(i=0;i<=s;i++) if(ks[i]>v) v=ks[i];
printf("%d ",v);
return 0;
}
int value(int x)
...{
int ans=1;
int i;
if(x==1) return 0;
for(i=2;i<x;i++)
if(!(x%i)) ans+=i;
return ans;
}
- 背包问题经典实现方法
- 背包问题经典模型
- 01背包经典问题
- 背包问题(经典)
- 0-1背包问题经典算法(递归实现)
- 0-1背包问题经典算法(二维数组实现)
- 0-1背包问题经典算法(一维数组实现)
- 经典背包问题 01背包+完全背包+多重背包
- 经典背包问题 01背包+完全背包+多重背包
- 经典背包问题 01背包+完全背包+多重背包
- 经典背包问题 01背包+完全背包+多重背包
- 经典背包问题 01背包+完全背包+多重背包
- 经典背包问题 01背包+完全背包+多重背包
- 经典背包问题 01背包+完全背包+多重背包
- 经典背包问题----(01背包、完全背包、多重背包)
- 经典的01背包问题
- 经典背包问题 POJ 3624
- 经典的01背包问题
- 不是我不明白这世界变化快 姚麦在一无所有中呐喊
- 给年轻工程师的10大忠告
- 学习.NET remoting 啦!
- ASP.NET 2.0的新特征
- RouterOS - 网络中配置一台DMZ站点
- 背包问题经典实现方法
- RouterOS - 端口映射
- RouterOS - 怎么样把ROS的各种设定导出
- 关于Jive中的迭代器与代理模式
- 软件路由器经典十问
- 现代医学真的昌明吗
- 管理联机安全风险
- 我经历过的管理黑暗时代:团队骨干集体被挖!
- 浅谈《经济学原理》