-
问题
已知有一个最多可以装质量W的背包,还有N件物品,第i件物品的质量是w[ i ],价值是v[ i ],每种物品尽可以放一件,可以选者放或者不放,而且不可以超过背包的最大承受的重量 -
解析
假设一个A机器,一个B机器,有n个任务(n>=2),处理每个任务需要的时间为ai,按任务顺序,当A机器用j时间和B机器共处理了k个任务(0<=j<=a的和,2<=k<=n),那么有一函数F(k,j)可求出此时B机器用的最少时间。
当k=1,j<a[1]时,F(k,j)应为a[1];
当k=1,j>=a[1]时,F(k,j)应为0;
当k>1,j<a[k]时,A机器没时间处理该任务,则由B机器处理,即F(k,j)=F(k-1,j)+a[k];
当k>1,j>=a[k]时,A机器有时间处理该任务,但要和B机器处理的时间取最小值,因为完成k-1个任务时,A机器花费了j-a[k]的时长,因此F(k,j)=min{F(k-1,j)+a[k],F(k-1,j-a[k])。
当所有任务都完成,即k==n时,可求出最短时间:
对于每一个确定的F(k,j)应取F(k,j)和j的最大值,即max{j,F(k,j)},因为要取最晚结束的时间;在此基础上应取所有值的最小值为最短时间。
- 设计
for(int i = 1; i <= N; i++){
for(int j = 1; j <= W; j++){
if(j < w[i]) dp[i][j] = dp[i - 1][j]; //不装,因为装不下
//在可以装得前提下, 看看装还是不装哪一种情况可以使得价值更大;
else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i]);
}
}
4.分析
时间复杂度为O(n^2)
5.源码
https://github.com/woshichunchongchong/Algorithm_hw/blob/main/0-1%E8%83%8C%E5%8C%85.cpp
#include
#include
#include<string.h>
#include<limits.h>
#include
#define MAX_SIZE 500
using namespace std;
int max(int x, int y); //求最大值
int min(int x, int y); //求最小值
int solve(int a[], int n); //求最短时间
int main(){
int n; //任务数量
int a[MAX_SIZE]; //完成每项任务需要的时间
int ans; //最短时间
cout << “请输入任务总数:”;
cin >> n;
cout << “请输入完成每项任务需要的时间(用空格分开):”;
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
ans = solve(a, n);
cout << “两台机器完成全部任务的最短时间为:” << ans << endl;
return 0;
}
int max(int x, int y) {
if (x > y) {
return x;
}
else {
return y;
}
}
int min(int x, int y) {
if (x > y) {
return y;
}
else {
return x;
}
}
int solve(int a[], int n) {
int totle_time = 0; //所有任务共需时间
int dp[MAX_SIZE][MAX_SIZE]; //B机器所需的最短时间
int time[MAX_SIZE]; //最短时间
for (int i = 0; i < n; ++i) {
totle_time += a[i]; //计算所有任务共需时间
}
//当执行第1个任务时的情况
for (int j = 0; j < totle_time + 1; ++j) {
if (j < a[0]) {
dp[0][j] = a[0];
}
else {
dp[0][j] = 0;
}
}
//当执行第2至最后一个任务时的情况
for (int i = 1; i < n; ++i) {
time[i] = INT_MAX;
for (int j = 0; j < totle_time + 1; ++j) {
if (j < a[i]) {
dp[i][j] = dp[i - 1][j] + a[i]; //当执行的时间j小于A机器所需时间时,认为B机器执行第i+1个任务
}
else {
dp[i][j] = min(dp[i - 1][j] + a[i], dp[i - 1][j - a[i]]); //若B机器执行快,则选择在上一行的时间上加上第i+1个任务需要的时间,否则令A机器执行
}
time[i] = min(time[i], max(j, dp[i][j]));
}
}
// for (int i = 0; i < n; ++i) {
// for (int j = 0; j < totle_time + 1; ++j) {
// cout<<dp[i][j]<<" ";
// }
// cout<<endl;
// }
return time[n - 1];
}