动态规划----最小重量机器设计

最小重量机器设计

题目

设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得。设Wij 是
从供应商j处购得的部件i的重量,Cij 是相应的价格。
试设计一个算法,给出总价格不超过c的最小重量机器设计。
′编程任务:
对于给定的机器部件重量和机器部件价格,编程计算总价格不超过d的最小重量机器设
计。

输入描述
Input
第一行有 3 个正整数 n ,m和 d。接下来的 2n 行,每
行m个数。前n行是c,后n行是w。

输出描述
Output
将计算出的最小重量,以及每个部件的供应商输出

样本输入
Input example
3 3 4
1 2 3 3 2 1 2 2 2 1 2 3 3 2 1 2 2 2
样本输出
Output example
4
1 3 1

解答

/*大概思路类似于0/1背包问题,区别在于状态转移方程不一样
状态转移方程: f(i,j)=Min{ f(i-1,j-c[i][1])+w[i][1], f(i-1,j-c[i][2])+w[i][2], f(i-1,j-c[i][3])+w[i][3] ...f(i-1,j-c[i][M])+w[i][M] }
其中f(i,j)表示在资金为j且仅考虑前i种部件下的最小重量。c[i][j]表示第j个商家的第i个商品的价格。w[i][j]表示第j个商家的第i个商品的重量。 
*/ 

#include<stdio.h>
#include<stdlib.h>
int n,m,d;
int *min;
int **which,*dis;
int **c,**w;
int MIN(int N,int D);
int main(){ 
	scanf("%d %d %d",&n,&m,&d); 
	min=(int *)malloc(sizeof(int)*d+1);
	c=(int **)malloc(sizeof(int *)*n+1);
	w=(int **)malloc(sizeof(int *)*n+1);
	which=(int **)malloc(sizeof(int *)*n+1);
	dis=(int *)malloc(sizeof(int)*d+1);
	for(int i=1;i<=n;i++){
	    c[i]=(int *)malloc(sizeof(int)*m+1);
	    w[i]=(int *)malloc(sizeof(int)*m+1);
	    which[i]=(int *)malloc(sizeof(int)*d+1);
	    for(int j=1;j<=m;j++){
	    	c[i][j]=0;
	    	w[i][j]=0;
		}
	}
	//以上是动态分配数组 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			scanf("%d",&c[i][j]);
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			scanf("%d",&w[i][j]);
		}
	}
	//以上测试数据输入 
	for(int i=0;i<=d;i++) min[i]=0;  //初始化min数组 
	printf("%d\n",MIN(n,d));   //计算最小重量 
	dis[n]=which[n][d];       //根据which数组(whic数组记录每个子问题选择的商家)记录每个部件所选择的商家并输出 
	d=d-c[n][dis[n]];
	for(int i=n-1;i>=1;i--){
		dis[i]=which[i][d];
		d=d-c[i][dis[i]];
	}	
	for(int i=1;i<=n;i++) printf("%d ",dis[i]);
	return 0;
}
int MIN(int N,int D){
	int *IFMIN,minw;
	int I;
	IFMIN=(int *)malloc(sizeof(int)*m+1);
	for(int nf=1;nf<=N;nf++){
		for(int df=D;df>=0;df--){
			for(int i=1;i<=m;i++){
				if(c[nf][i]==0) continue; 
				if((df-c[nf][i]<0)||(min[df-c[nf][i]]==-1)) IFMIN[i]=-1;
				else{
					IFMIN[i]=min[df-c[nf][i]]+w[nf][i];
				}
			}
			for(I=1;I<=m;I++) { if(IFMIN[I]!=-1){ minw=I; break; } }
        	for(;I<=m;I++) { if((IFMIN[I]!=-1)&&IFMIN[I]<IFMIN[minw]) minw=I;}
        	min[df]=IFMIN[minw];
        	which[nf][df]=minw;
		}
	}
	free(IFMIN);
	return min[D];
}

测试数据

输入:
8 18 14
18 15 20 5 15 10 16 6 1 6 17 6 1 2 17 15 13 17
16 6 7 4 7 2 11 6 18 4 13 12 8 5 2 8 15 14
12 6 19 10 13 8 2 10 16 4 15 15 16 13 17 12 14 4
18 18 2 13 15 19 5 12 18 7 13 9 8 17 10 13 15 11
8 5 14 11 18 20 17 3 11 17 13 11 4 9 17 14 19 1
10 7 8 11 13 3 19 3 12 11 12 14 4 2 12 10 14 15
12 9 13 9 16 17 12 15 6 3 11 17 13 17 14 13 4 4
19 12 3 19 3 20 19 12 8 19 8 10 19 20 3 1 7 1
16 12 4 16 2 6 15 1 13 3 7 16 5 3 16 16 14 19
12 14 6 2 11 15 9 17 15 16 19 20 14 14 20 9 4 4
6 13 16 6 3 12 12 19 11 20 4 13 9 18 7 17 8 1
4 17 3 20 3 8 12 7 4 12 6 12 1 18 13 20 20 8
4 15 1 10 2 12 8 11 5 4 20 13 12 20 1 3 3 11
1 9 2 1 16 1 12 4 5 2 7 15 12 3 9 4 13 6
13 1 10 8 5 13 20 10 6 4 8 15 8 8 20 11 9 9
2 10 11 1 18 8 20 11 18 2 3 6 14 16 19 4 3 15
输出:
57
13 6 7 3 18 14 10 16
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值