(动态规划)计算机算法设计与分析课后题

3-1最优调度

3-2任务批处理

*3-3石子合并问题
石子合并问题中首先令dp[i][j](i<j)代表石子堆i到石子堆j的情况,分为最大得分情况和最小得分情况,每次的得分等于不同情况下的得分加从i到j的和例如在数字为4,4,5,9时:
dp[1][2]=dp[1][1]+dp[2][2]=]=0+0+sum12=4+4=8;
dp[2][3]=dp[2][2]+dp[3][3]+sum23=9;
dp[1][3]=dp[1][1]+dp[2][3]=0+sum13+dp[2][3]=13+9=22
=dp[1][2]+dp[3][3]=8+sum13=8+13=21;………
所以由递推公式可知需要先计算dp[1][2],dp[2][3].dp[3][4]……然后通过数组进一步求解其他的情况,最终得到dp[1][4],因为每次都有不同情况所以需要对每种情况进行比较,将最小得分情况存入一个数组,最大得分情况存入另一个数组。最终得到两个数组中i=1,j=4的对应位置的值
最小得分数组:
在这里插入图片描述

需要三重循环,对二维数组填数从红框标注的开始依次向上填最终得到最小分数。
最大得分数组同理
代码:

1.	#include<iostream>  
2.	#include<algorithm>  
3.	#include<fstream>  
4.	using namespace std;  
5.	int dpmin[1024][1024] = { 0 }, dpmax[1024][1024] = { 0 };//一个存放最大一个存放最小  
6.	int sum[10] , a[10];  
7.	void Intereslove(int n) {  
8.	    for (int length = 2; length <= n; ++length) {  
9.	        for (int begin = 1; begin <= n - length + 1; ++begin) {  
10.	            int end = begin + length - 1;  
11.	            dpmin[begin][end] = 200000;//由题目可得最多为200000个石子如dp[i][j]表示1-j的最大合并得分  
12.	            dpmax[begin][end] = -1;//设置一个负数  
13.	            int temp = sum[end] - sum[begin - 1];//从begin开始到end结束的数字和  
14.	            for (int k = begin; k < end; ++k) {  
15.	                dpmin[begin][end] = min(dpmin[begin][end], dpmin[begin][k] + dpmin[k + 1][end] + temp);  
16.	                dpmax[begin][end] = max(dpmax[begin][end], dpmax[begin][k] + dpmax[k + 1][end] + temp);  
17.	            }  
18.	        }  
19.	    }  
20.	}  
21.	void main() {  
22.	    ifstream inFile("input3-3.txt");  
23.	    ofstream outFile("output3-3.txt");  
24.	    int n, datalen=025.	    int nm[10];  
26.	    while (!inFile.eof()) {  
27.	        inFile >> nm[datalen++];  
28.	    }  
29.	    int a[10];  
30.	    n = nm[0];  
31.	    for (int i = 0; i < n; i++)a[i] = nm[i+1] ;  
32.	    sum[0] = 0;  
33.	    for (int i = 1; i <= n; i++) {  
34.	        sum[i] = sum[i - 1] + a[i-1];  
35.	    }  
36.	    Intereslove(n);  
37.	    outFile << dpmin[1][4]<<endl;  
38.	    outFile << dpmax[1][4];  
39.	    inFile.close();  
40.	    outFile.close();  
41.	  
42.	}  

结果:
在这里插入图片描述

3-4数字三角形问题
每次选择一个位置往上走,然后找最优值,每次可以选很多种走法,每次找最优,i,j表示位置
数字三角形问题,从顶部向下,每次都可以走(I,j),(i,j+1)两种走法所以需要的数组中存储的是从(i,j)走的最大的路径,因此用D[i][j]存储点(i,j),maxsum[i][j]存储点(i,j)到底边路径的最大和。由于点(i,j)只能向(i+1,j)和(i+1,j+1)走,可以自底向上计算从最后一行往上计算,算完的值存在maxsum中,最后一行不需要行走所以可以全部赋值为-1,将第四行全部置为数组元素值,然后依次向顶部计算。
Max[i][j]=max(Max[i+1][j],Max[i+1][j+1])+a[i][j]
在这里插入图片描述

1.	#include <iostream>  
2.	#include <algorithm>  
3.	#include<fstream>  
4.	using namespace std;  
5.	int D[20][20];  
6.	int n;  
7.	int maxsum[20][20] = { 0 };  
8.	//递推法,从下往上计算  
9.	void Shorest(){  
10.	for (int j = 0; j < n; j++)  
11.	    maxsum[n - 1][j] = D[n - 1][j];  
12.	for (int i = n - 2; i >= 0; i--)  
13.	for (int j = 0; j <= i; j++)  
14.	maxsum[i][j] = max(maxsum[i + 1][j], maxsum[i + 1][j + 1]) + D[i][j];  
15.	cout << maxsum[0][0];  
16.	}  
17.	void  main()  
18.	{  
19.	    ifstream inFile("input3-4.txt");  
20.	    ofstream outFile("output3-4.txt");  
21.	    inFile >> n;  
22.	    for (int i = 0; i <= n; i++) {  
23.	        for (int j = 0; j <= i; j++) {  
24.	            inFile>> D[i][j];  
25.	        }  
26.	    }  
27.	    Shorest();  
28.	}  

结果:
在这里插入图片描述

3-5乘法表
3-6租用游艇
3-7汽车加油行驶

3-8最小m段和问题
dp(i,j)表示i个数分为j段,所以有
dp[i][j]=min(max{dp[k][j],sum(k,i)},max{dp[j][j-1]),a[i]}) k =j:i-1
分析:
在这个式子中的每种情况首先计算对于前k个数划分为j段的情况与从k加到最后的j位数的最大值,然后与从前k个数划分j-1段,即把最后一个数字单独作为一段的情况,计算两个值的最小值
对dp数组进行初始化,初始化dp[1][1],dp[2][1],dp[3][1]……就是把所有的数都只分为一个段,也就是前i个数的和。进行累计计算
用5个数字举例
假设数字是2,1,3,0,4
I表示数的个数,j表示段数
数组:
在这里插入图片描述

通过查表即可以得到最终答案。
最开始红色部分为初始化过的,然后用递推公式依次计算得到数据,例如:
dp[5][1]=min{max{dp[4][2],sum45},max{dp[3][2],sum35},max{dp[4][1],s[5]}
在这里插入图片描述

代码:
1.	#include<iostream>  
2.	#include<fstream>  
3.	#include<algorithm>  
4.	using namespace std;  
5.	int dpm[6][6] = { 0 };  
6.	int n = 5;  
7.	void min_m(int *a) {  
8.	    for (int i = 1; i <= n; i++)   
9.	        for (int j = 2; j < i; j++) {  
10.	            dpm[i][j]= max(dpm[i - 1][j - 1], a[i - 1]);//dpm数组从1开始,a从零开始  
11.	            for (int k = j; k <i; k++) {  
12.	                if (dpm[i][j] > max(dpm[k][j], dpm[i][1] - dpm[k - 1][1]))  
13.	                    dpm[i][j] = max(dpm[k][j], dpm[i][1] - dpm[k - 1][1]);  
14.	            }  
15.	        }  
16.	}  
17.	int sum(int* a, int i) {  
18.	    int res=0;  
19.	    for (int j = 0; j < i; j++) {  
20.	        res += a[j];  
21.	    }  
22.	    return res;  
23.	}  
24.	void main() {  
25.	    int a[5] = { 2,1,3,0,4 };  
26.	    //dpm数组进行初始化  
27.	    for (int i = 1; i <= n; i++) {  
28.	        dpm[i][1] = sum(a, i);  
29.	        dpm[i][i] = *max_element(a,a+i);  
30.	}  
31.	    min_m(a);  
32.	}  

3-10最大长方体问题

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值