回溯 0-1背包&最佳调度

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值