0-1背包
给定n(n<=100)种物品和一个背包。物品i的重量是wi,价值为vi,背包的容量为C(C<=1000)。问:应如何选择装入背包中的物品,使得装入背包中物品的总价值最大? 在选择装入背包的物品时,对每种物品i只有两个选择:装入或不装入。不能将物品i装入多次,也不能只装入部分物品i。
输入格式:
共有n+1行输入: 第一行为n值和c值,表示n件物品和背包容量c; 接下来的n行,每行有两个数据,分别表示第i(1≤i≤n)件物品的重量和价值。
输出格式:
输出装入背包中物品的最大总价值。
输入样例:
在这里给出一组输入。例如:
5 10
2 6
2 3
6 5
5 4
4 6
输出样例:
在这里给出相应的输出。例如:
15
dfs //可能超时
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
struct Data
{
double weight;
double value;
}a[100];
int n, c;
int values = 0;
int bestvalues = 0;
int weights = 0;
int r = 0; //剩余物品的价值
void backtrack(int k)
{
int i;
if (k > n - 1)
{
if (values > bestvalues)
{
bestvalues = values;
}
}
else
{
for ( i = 0; i <= 1; i++) //装或不装两种情况
{
if (i == 0 && values + r > bestvalues) //右分支
{
backtrack(k + 1);
}
else if (weights + a[k].weight <= c) //左分支
{
weights += a[k].weight;
values += a[k].value;
r -= a[k].value;
backtrack(k + 1); //下一个物品
values -= a[k].value; //回溯,不装k
weights -= a[k].weight;
r += a[k].value;
}
}
}
}
bool cmp(Data d1, Data d2)
{
return d1.value/d1.weight > d2.value/d2.weight;
}
int main()
{
cin >> n >> c;
for (int j = 0; j < n; j++)
{
cin >> a[j].weight >> a[j].value;
r += a[j].value;
}
sort(a, a + n, cmp);
backtrack(0);
cout << bestvalues << endl;
return 0;
}
枚举 //可能超时
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
struct Data
{
double weight;
double value;
}a[100];
int n, c;
int values = 0;
void trackback(int i,double w,double v) {
if (i>n-1)
{
if (w <= c)
values = values > v ? values : v;
return;
}
else
{
w += a[i].weight;
v += a[i].value;
trackback(i + 1, w, v);
w -= a[i].weight;
v -= a[i].value;
trackback(i + 1, w, v);
}
}
bool cmp(Data d1, Data d2)
{
return d1.value/d1.weight > d2.value/d2.weight;
}
int main()
{
cin >> n >> c;
for (int j = 0; j < n; j++)
cin >> a[j].weight >> a[j].value;
sort(a, a + n, cmp);
trackback(0, 0, 0);
cout << values << endl;
return 0;
}
dp
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int n, c;
int dp[1111];
int w[100];
int v[100];
int main() {
cin >> n >> c;
for (int i = 1; i <= n; i++) {
cin >> w[i] >> v[i];
}
for (int i = n; i >= 1; i--) // or 1 - n
{
for (int j = c; j >= 0; j--) //容量j下最大值
{
if (j >= w[i])
dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
}
}
cout << dp[c] << endl;
return 0;
}
最佳调度
假设有n(n<=20)个任务由k(k<=20)个可并行工作的机器完成。完成任务i需要的时间为ti。 试设计一个算法,对任意给定的整数n和k,以及完成任务i 需要的时间为ti ,i=1~n。计算完成这n个任务的最佳调度,使得完成全部任务的时间最早。
输入格式:
输入数据的第一行有2 个正整数n和k。第2 行的n个正整数是完成n个任务需要的时间。
输出格式:
将计算出的完成全部任务的最早时间输出到屏幕。
输入样例:
在这里给出一组输入。例如:
7 3
2 14 4 16 6 5 3
输出样例:
在这里给出相应的输出。例如:
17
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
static int INF = 0x3f3f3f3f;
int n, k;
int* a;
int* num ;
int shortest = INF;
void backtrack(int i)
{
if (i > n - 1)
{
int max = 0;
for (int q = 0; q < k; q++)
max = max > num[q] ? max : num[q];
shortest = shortest < max ? shortest : max;
}
else
{
for (int j = 0; j < k; j++)
{
num[j] += a[i];
if (num[j] < shortest) //剪枝
{
backtrack(i + 1);
}
num[j] -= a[i]; 第j个机器不执行第i个任务
}
}
}
bool cmp(int d1, int d2)//比较器
{
return d1 > d2;
}
int main()
{
cin >> n >> k;
a = new int[n];
num = new int[k];
for (int p = 0; p < k; p++)
num[p] = 0;
for (int i = 0; i < n; i++)
cin >> a[i];
backtrack(0);
cout << shortest << endl;
return 0;
}