oj_18.04.19

1.数字三角形问题

问题描述:

给定一个由n行数字组成的数字三角形如下图所示。试设计一个算法,计算出从三角形的顶至底的一条路径,使该路径经过的数字总和最大。

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

问题分析:该问题的关键是,并非可以随意选择一层中的任意一个数字,路径的意思是层与层之间经过的数字是相邻的,因此不能用从n-1层递归到n层的思想。因此,本题的求解还是暴力求解,不过可以通过保存运算结果来避免重复计算,加快求解速率。

因此,建立另外一个二维数组,仅仅初始化最底层,然后不断通过对比来确定上一层,保存在二维数组中的值,是已经淘汰掉一些不可能是最优的情况,最后保存在B[0][0]的值为最大值。

代码如下:

#include <iostream>
using namespace std;


int main(){
	int n;
	cin>>n;
	int A[100][100];
	int B[100][100];
	for(int i=0;i<n;i++){
		for(int j=0;j<=i;j++) cin>>A[i][j];
	}
	for(int j=0;j<n;j++) B[n-1][j] = A[n-1][j];
	for(int i=n-1;i>0;i--){
		for(int j=0;j<i;j++){
 			if(B[i][j] > B[i][j+1]) 
				B[i-1][j] = B[i][j] + A[i-1][j];
			else B[i-1][j] = B[i][j+1] + A[i-1][j];
		}
	}
	cout<<B[0][0]<<endl;
}

2.租用游艇问题

问题描述:

  长江游艇俱乐部在长江上设置了个游艇出租站12,…,n。游客可在这些游艇出租站租用游艇,并在下游的任何一个游艇出租站归还游艇。游艇出租站到游艇出租站之间的租金为r(i,j),1£i<j£n。试设计一个算法,计算出从游艇出租站到游艇出租站所需的最少租金。 要求:对于给定的游艇出租站到游艇出租站之间的租金为r(i,j),1£i<j£n,编程计算从游艇出租站到游艇出租站n所需的最少租金。

问题分析:该问题其实就是最短路径问题。

代码如下:

#include <iostream>
#include <limits.h>
using namespace std;

int main(){
	int n;
	cin>>n;
	int A[201][201];
	for(int i=1;i<n;i++){
		for(int j=i+1;j<=n;j++)
			cin>>A[i][j];
	}
	for(int i=1;i<=n;i++){
		A[i][i] = 0;
	}
	for(int k=2;k<n;k++)  {  
        for(int i=1;i<=n-k;i++)  {  
            int j=i+k;  
            for(int z=i+1;z<=j;z++)  {  
                int temp = A[i][z]+A[z][j];  
                if(A[i][j]>temp)  
                    A[i][j]=temp;  
            }  
        }  
    }  
	cout<<A[1][n]<<endl;
}
3.最大K乘积问题
问题描述:

I是一个n位十进制整数。如果将I划分为k段,则可得到k个整数。这k个整数的乘积称为I的一个k乘积。试设计一个算法,对于给定的Ik,求出I的最大k乘积。

问题分析:这同样是个动态规划问题,拥有最优子结构性质,可以用递推来求解。

  设I(s,t)是I的从s位开始的t位数字组成的十进制数,FindMax(i,j)表示I(0,i)的最大j乘积。动态规划递推式如下:

FindMax(i,j) = max{FindMax(k,j-1)*I(k,i-k)}    (1<=k<i)

代码如下:

#include <iostream>
#include <limits.h>
using namespace std;

int I(int s,int t,int A[]){
	int sum = 0;
	for(int i=0;i<t;i++) sum = sum*10 +A[s+i];
	return sum;
}

int FindMax(int i,int j,int A[]){
	if(j == 1) {
		return I(0,i,A);
	}
	int max = 0;
	for(int k=1;k<i;k++){
		if((FindMax(k,j-1,A)*I(k,i-k,A)) > max ) max = (FindMax(k,j-1,A)*I(k,i-k,A));
	}
	return max;
}

int main(){
	int n,k,num;
	cin>>n>>k>>num;
	int static A[11];
	for(int i=n-1;i>=0;i--){
		A[i] = num % 10;
		num = num / 10;
	}
	cout<<FindMax(n,k,A)<<endl;
}


猜你喜欢

转载自blog.csdn.net/CityChan96/article/details/80008375
OJ