回溯法简单练习

不等式求解

总时间限制:
1000ms
内存限制:
32768kB
描述

有关于变元x1,x2,x3…xn的不等式: k1x1+ k2x2+ k3x3+ … + knxn<= y. 其中ki, y都是正整数

求所有的非负整数解

输入
输入文件包括两行

第一行是n, 1<=n<=7

第二行包含n+1个用空格分隔的正整数, 分别表示k1, k2…kn, y

输出
输出文件一行一组解, 每一行有n个用空格分隔的非负整数, 分别表示这组解的x1,x2…xn

所有的解按照x1为第一关键字, x2为第二关键字…从小到大排序

样例输入
2
1 2 3
样例输出
0 0
0 1
1 0
1 1
2 0
3 0
提示
不等式中的所有整数均小于30
#include<iostream>
#include<cstdio>
#define N 10
using namespace std;
int n, y, tsum = 0;
int ans[N] = {};
int a[N] = {};
void retrack( int i ){
	int k;
	if( i == n ){
		for( k = 0; k < n; ++k )
			printf( "%d ", ans[k]);
			//cout << ans[k] << " ";
		printf("\n");
		return;
	}
	int l = y / a[i];
	for( k = 0; k <= l; ++k ){
		int t = k*a[i];
		if( tsum + t <= y && tsum + t >= 0){
			tsum += t;
			ans[i] = k;
			retrack(i+1);
			tsum -= t;
		}else
			break;
	}
}
int main(){
	cin >> n;
	int i;
	for( i = 0; i < n; ++i )
		cin >> a[i];
	cin >> y;
	retrack(0);
	//system("pause");
	return 0;
}

被cout和printf的巨大时间差坑了好久…

 

D:最小重量机器设计问题

总时间限制:
1000ms
内存限制:
32768kB
描述

某设备需要N种配件(编号1~N), 每种1个. 有M个供应商(编号1~M), 每一个供应商都能提供这N种配件.
然而, 不同供应商提供的同一种配件不仅有不同的价格, 也拥有不用的重量.
现在, 你可以从这M个供应商中任意购买N种配件(每种1个), 但是你只有V元钱.
求使得总重量最小的方案.

输入
第一行有3个正整数, 分别为N,M,V.

接下来的N行, 每一行都有2*M个用空格分开的正整数, 其中:

第i+1行的第2*j-1个数表示第j个供应商提供的第i种零件的价格(单位:元),

第i+1行的第2*j个数表示第j个供应商提供的第i种零件的重量

1<=i<=N, 1<=j<=M

输出
只有一行

如果没有可行方案, 输出-1

否则, 这一行应该包含用空格分隔的N个整数, 第i个整数表示你选择的第i种零件的供应商.

如果有多个方案, 那么输出第1种零件供应商编号最小的那个, 如果还是有多个, 输出第2种零件供应商编号最小的那个, 类推.

样例输入
2 2 10
6 2 4 1
5 1 3 1
样例输出
2 1
提示
N和M均不超过8

所有配件的重量和价格都是不超过50的正整数

样例解释: 第一个供应商提供的1号配件价格是6, 重量是2. 2号配件价格是5, 重量是1. 第二个供应商提供的1号配件价格是4, 重量是1. 2号配件价格是3, 重量是1.

最小的重量和显然是2, 可以两种配件都选择第二个供应商, 也可以1号配件选第二个, 2号配件选择第一个供应商

根据题目表述,应该选择后面这个方案

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int N, M, V;
struct ITEM{
	int price;
	int weight;
}item[10][10];
int ans[10] = {};
int tmp[10] = {};
int answ = 999999;
void reback( int tprice, int tw, int id ){
	int i;
	if( tprice > V )
		return;
	if( id > N ){
		if( answ > tw ){
			answ = tw;
			for( i = 1; i <= N; ++i )
				ans[i] = tmp[i];
		}
		return;
	}
	for( i = 1; i <= M; ++i ){
		tmp[id] = i;
		reback( (tprice + item[id][i].price), (tw + item[id][i].weight ), id+1);
	}
}

int main(){
	cin >> N >> M >> V;
	int i, j;
	for( i = 1; i <= N; ++i ){
		for( j = 1; j <= M; ++j )
			cin >> item[i][j].price >> item[i][j].weight;
	}
	reback( 0, 0, 1 );
	if( answ == 999999)
		printf("-1\n");
	else{
		for( i = 1; i <= N; ++i )
			printf( "%d ", ans[i]);
		printf("\n");
	}
	return 0;
}

这题看起来很像是可以用背包来做。。。不过提示这样写就很明显回溯的顺序了..

 

    原文作者:回溯法
    原文地址: https://blog.csdn.net/u012068540/article/details/24205603
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞