algm课后作业-dp

这篇博客探讨了动态规划在解决一系列问题中的应用,包括链条切割问题、机器人路径规划、租用游艇的最优化选择、矩阵链乘法求解最小代价、石子合并的区间DP策略以及数字三角形的最短路径。通过自底向上的计算方法,展示了如何有效地计算最优解,并提供了相应的代码实现。
摘要由CSDN通过智能技术生成

NO.1 链条切割问题
NO.2 机器人两次走路
NO.3 租用游艇
NO.4 矩阵链乘
NO.5 石子合并-区间dp
NO.6 数字三角形
------自底向上计算—

//长度为n的链条进行切割  

#include<bits/stdc++.h>
using namespace std;
const int N=10010;
const int minn=0x0c0c0c0c;
int a[N],n,r[N];

int main(){
	cin>>n;
	for(int i=1;i<=10;i++) cin>>a[i];
	for(int i=11;i<=n;i++) a[i]=a[10];
	for(int i=1;i<=n;i++){
		for(int j=1;j<=i;j++){
			r[i]=max(r[i],a[j]+r[i-j]);
		}
	}
	
	cout<<r[n]<<endl;
	
	return 0;
} 

/*
13
1 5 8 9 10 17 17 20 24 30
*/
#include<bits/stdc++.h>
using namespace std;
int mp[101][101];
int dp[101][101][101][101],n,a,b,c;

void  fun( int  x1, int  y1, int  x2, int  y2, int  t){
    if(x1==x2&&y1==y2)
        dp[x1][y1][x2][y2]=max(dp[x1][y1][x2][y2],t+mp[x1][y1]);
    else
        dp[x1][y1][x2][y2]=max(dp[x1][y1][x2][y2],t+mp[x1][y1]+mp[x2][y2]);
}

int main(){
	cin>>n;
	while(cin>>a>>b>>c){
		if(!a&&!b&&!c) break;
		mp[a][b]=c;
	}
	
	//自底向上推导 
	dp[1][1][1][1]=mp[1][1];
	for(int s=2;s<=2*n-1;s++){
		for(int x1=1;x1<=s-1;x1++){
			for(int x2=1;x2<=s-1;x2++){
				int y1=s-x1;
				int y2=s-x2;
				int t=dp[x1][y1][x2][y2];
				fun(x1+1,y1,x2+1,y2,t);
                fun(x1+1,y1,x2,y2+1,t);
                fun(x1,y1+1,x2+1,y2,t);
                fun(x1,y1+1,x2,y2+1,t);
			}
		}
	}
	cout<<dp[n][n][n][n]<<endl;
	
	return 0;
}

/*
8
2 3 13
2 6 6
3 5 7
4 4 14
5 2 21
5 6 4
6 3 15
7 2 14
0 0 0
*/
//租用游艇问题
#include<bits/stdc++.h>
using namespace std;
const int N=5010;
int n;
int a[N][N],dp[N];

//自底向上 
int fun(){
	for(int i=2;i<=n;i++){
		dp[i]=a[1][i];
		for(int j=2;j<i;j++){
			dp[i]=min(dp[i],dp[j]+a[j][i]); 
		}
	}
	return dp[n];
}

int main(){
	cin>>n;
	for(int i=1;i<n;i++){
		for(int j=i+1;j<=n;j++){
			cin>>a[i][j];
		}
	}
	cout<<fun()<<endl;
	
	return 0;
} 

/*
3
10 1
7
*/

bug一会再调–zhidaole ok

//注意的地方--在i-j循环中,第一层i从小到大,j要从i到小,为什么
//因为M[1][4]依赖于M[2][4],M[2][4]依赖于M[3][4] 
#include<bits/stdc++.h>
using namespace std;
const int N=5050;
const int inf=0x3f3f3f3f;
int a[N],M[N][N],s[N][N],n,p;

void print(int i,int j){
	if(i==j) cout<<"A"<<i;
	else{
		cout<<"(";
		print(i,s[i][j]);
		print(s[i][j]+1,j);
		cout<<")";
	}
}

int main(){
	cin>>n;
	//注意的地方--(n-1)个矩阵,记录n个值 i-i+1 
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n-1;i++){
		for(int j=i-1;j>=1;j--){
//		for(int j=1;j<i;j++){  × 
			
			M[j][i]=inf;
			for(int k=j;k<i;k++){
				int p=M[j][k]+M[k+1][i]+a[j]*a[k+1]*a[i+1];
				if(p<M[j][i]){
					M[j][i]=p;
					s[j][i]=k;
				}
			}	
		}
	}

	cout<<M[1][n-1]<<endl;
	print(1,n-1);
	
	
	return 0;
}

/*
6
5  10  4  6  10  2
348
*/


#include<bits/stdc++.h>
using namespace std;
const int N=301;
const int inf=0x3f3f3f3f;
int a[N],n,s[N];
int dp[N][N];

int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		s[i]=s[i-1]+a[i];
	} 
	
	//枚举长度 
	for(int len=1;len<n;len++){
		for(int i=1;i+len<=n;i++){
			int j=i+len;
			dp[i][j]=inf;
			for(int k=i;k<j;k++){
				dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+s[j]-s[i-1]);
			}
		}
	}
	cout<<dp[1][n]<<endl;
	
	return 0;
}

/*
4
1 3 5 2
*/
//自底向上
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=510;
int n;
int f[N][N];//从第i行j列走到最后一行的数字和 
int w[N][N];//第i行j列的数值 

int main(){
	cin>>n;
	//第n行有n个数 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=i;j++){
			cin>>w[i][j];
		}
	}	
	for(int i=1;i<=n;i++) f[n][i]=w[n][i];
	
	for(int i=n-1;i>0;i--){
		for(int j=1;j<=i;j++){
			f[i][j]=max(f[i+1][j],f[i+1][j+1])+w[i][j];
			 
		}
	}
	
	cout<<f[1][1]<<endl;
	return 0;
	
} 
/*
5
7 
3 8
8 1 0
2 7 4 4
4 5 2 6 5
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值