码迷,mamicode.com
首页 > 其他好文 > 详细

DP —— 数字三角形模型

时间:2021-03-16 11:57:25      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:ems   problem   star   tar   cin   algo   ble   out   循环   

0. 数字三角形

题目地址:

  1. 数字三角形 https://www.acwing.com/problem/content/900/

题目思路:

二维基础DP,每个 \(f[i,j]\) 都是从 \(f[i-1,j-1]\)\(f[i-1,j]\) 转移过来,取 \(max\) ,最后循环最下层,取 \(max\) 即为答案

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 510;

int g[N][N];
int dp[N][N];
int INF = 1e9;

int main()
{
	int n;
	cin >> n;
	
	for(int i = 1 ; i <= n ; i++)
		for(int j = 1; j <= i ; j++)
			cin >> g[i][j];
	
	for (int i = 0; i <= n; i ++ )
        for (int j = 0; j <= i + 1; j ++ )
            dp[i][j] = -INF;  //初始化所有值,防止边界情况出现问题
			
	dp[1][1] = g[1][1];
	for(int i = 2; i <= n ; i++)
		for(int j = 1 ; j <= i ; j++)	
			dp[i][j] = g[i][j] + max(dp[i-1][j-1],dp[i-1][j]);
	
	int ans = -INF;
	for(int i = 1; i <= n ; i++)
		ans = max(ans,dp[n][i]);
		
	cout << ans << endl;
	return 0;
}

1. 摘花生

题目地址:

  1. 摘花生 https://www.acwing.com/problem/content/1017/

题目思路:

二维基础DP,每个 \(f[i,j]\) 都是从 \(f[i-1,j]\)\(f[i,j-1]\) 转移过来,取 \(max\) ,最后输出 \(f[n,m]\) 即可

代码:

#include<bits/stdc++.h>
using namespace std;

const int N = 110;

int n,m;
int w[N][N];
int f[N][N];

int main()
{
	int T;
	cin >> T;
	while(T--)
	{
		cin >> n >> m;
		for(int i = 1; i <= n ; i++)
			for(int j = 1 ; j <= m ; j++)
				cin >> w[i][j];
		
		for(int i = 1 ; i <= n ; i++)
			for(int j = 1 ; j <= m ; j++)
				f[i][j] = max(f[i-1][j],f[i][j-1]) + w[i][j];
		
		cout << f[n][m] << endl;
	}
} 

2. 最低通行费用

题目地址:

  1. 最低通行费 https://www.acwing.com/problem/content/1020/

题目思路:

与摘花生相同,只需要分析出 \(2n-1\) 的意思是不走回头路,然后将摘花生的 \(max\) 改为 \(min\) 即可,但因为求最小值需要注意边界值的特殊情况

代码:

#include<bits/stdc++.h>
using namespace std;

const int N = 110;
int g[N][N];
int dp[N][N] = {0};

int main()
{
	int n;
	cin >> n;
	memset(dp,0x3f,sizeof dp);
	for(int i = 1 ; i <= n ; i++)
		for(int j = 1 ; j <= n ; j++)
			cin >> g[i][j];
	
	for(int i = 1 ; i <= n ; i++)
		for(int j = 1 ; j <= n ; j++)
			if(i==1 && j==1) dp[i][j] = g[i][j];
			else dp[i][j] = min(dp[i-1][j],dp[i][j-1]) + g[i][j];

	cout << dp[n][n];
} 

3. 方格取数

题目地址:

  1. 方格取数 https://www.acwing.com/problem/content/1029/

题目思路

与摘花生类似,但是需要本题为走两次, \(f[i_1,j_1,i_2,j_2]\) 表示所有从 \((1,1),(1,1)\) 分别走到 \((i_1,j_1),(i_2,j_2)\) 的路径的最大值

需要考虑 —— 如何处理 “同一个各自不能被重复选择”

进一步思考得出:只有在 \(i_1+j_1 == i_2 + j_2\) 时,两条路径的格子才可能重合

那么就可以优化成 \(f[k,i_1,i_2]\) 分别表示从 \((1,1),(1,1)\) 分别走到 \((i_1,k-i_1),(i_2,k-i_2)\) 的路径的最大值, \(k\) 表示当前走到坐标的横纵坐标之和

\(f[k][i_1][i_2]\) 作为最后一步时,两条线路分别有4种可能 —— 下下,下右,右下,右右 就分别对应 \(f[k-1][i1-1][i2-1]\) , \(f[k-1][i1-1][i2]\) , \(f[k-1][i1][i2-1]\) , \(f[k-1][i1][i2]\)

\(max\) 即可得出本题答案

代码

#include<bits/stdc++.h>
using namespace std;

const int N = 15;

int n;
int w[N][N];
int f[N*2][N][N];

int main()
{
	cin >> n;
	
	int a,b,c;
	while(cin >> a >> b >> c, a || b ||c) w[a][b] = c;
	
	for(int k = 2; k <= n + n ; k++)
		for(int i1 = 1 ; i1 <= n ; i1++)
			for(int i2 = 1 ; i2 <= n ; i2++)
			{
				int j1 = k - i1, j2 = k - i2;
				if(j1 >= 1 && j1 <= n && j2 >= 1 && j2 <= n)
				{
					int t = w[i1][j1];
					if(i1 != i2) t += w[i2][j2];
					int &x = f[k][i1][i2];
					x = max(x,f[k-1][i1-1][i2-1] + t);
					x = max(x,f[k-1][i1-1][i2] + t);
					x = max(x,f[k-1][i1][i2-1] + t);
					x = max(x,f[k-1][i1][i2] + t);
				}
			}
	
	cout << f[n+n][n][n] << endl;
}

DP —— 数字三角形模型

标签:ems   problem   star   tar   cin   algo   ble   out   循环   

原文地址:https://www.cnblogs.com/ieeeev/p/14532274.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!