方格取数———dp思想

题目:方格取数
拓展题:传纸条
题目大意:给定一个矩阵每一个位置有一个权值,从左上角到右下角,要走两次,所到的点如果有权值就取出并变为0,求所走路线取值和最大值。
解题思路:dp算法

	首先假设两条路同时出发,如果相遇在同一个各自就只需要取一次权值。

	这里我们来考虑状态:k表示当前所在位置步数(下标和,即x+y),i1表示第一条路线所在位置的行,i2表示第二条路线当前所在位置的行,即dp[k][i][j]。
因为判断是否在同一个位置的条件就是步数(下标和)相同的请情况下,两条路线在同一行,那么必定在同一列。

	现在来考虑状态转移:每一条路线的每一个位置都可以会从他的上方或者他的左边取过来,因为有两条路所以就会有4个状态转移。

上代码:

#include<bits/stdc++.h>
using namespace std;
const int N=27;
int w[N][N],dp[N][N][N];//dp[k][i1][i2]表示在k步数下,第一条路线所在行i1,第二条路线所在行i2
int main(){
	int n,a,b,c;
	cin>>n;
	while(cin>>a>>b>>c,a||b||c){//输入数据
		w[a][b]=c;
	}
	for(int k=2;k<=n+n;k++){//k的取值为2开始,到n+n,因为起点从(1,1)开始,终点为(n,n)
		for(int i1=1;i1<=n;i1++){//枚举每一步数下,第一条路所在行
			for(int i2=1;i2<=n;i2++){//枚举每一步数下,第二条路所在行
				int j1=k-i1,j2=k-i2,t=w[i1][j1];//可由步数和所在行,求出他们所在的列,t为第一条路线所在位置(i1,j1)的权值
				if(j1>=1&&j1<=n&&j2>=1&&j2<=n){//判断所在位置是否合法
					if(i1!=i2)t+=w[i2][j2];//如果不在同一个位置(就加上第二条路上所在位置(i2,j2)的权值)
					//以下为状态转移
					dp[k][i1][i2]=max(dp[k][i1][i2],dp[k-1][i1-1][i2-1]+t);
					//当前这一步可以由上一步时,第一条路线所在位置的左边,第二条路线所在位置的左边转移过来。
					dp[k][i1][i2]=max(dp[k][i1][i2],dp[k-1][i1-1][i2]+t);
					//当前这一步可以由上一步时,第一条路线所在位置的左边,第二条路线所在位置的上边转移过来。
					dp[k][i1][i2]=max(dp[k][i1][i2],dp[k-1][i1][i2-1]+t);
					//当前这一步可以由上一步时,第一条路线所在位置的上边,第二条路线所在位置的左边转移过来。
					dp[k][i1][i2]=max(dp[k][i1][i2],dp[k-1][i1][i2]+t);
					//当前这一步可以由上一步时,第一条路线所在位置的上边,第二条路线所在位置的上边转移过来。

					//因为k-1表示为上一步,i1,i2不变可表示上一个位置的j1,j2
				}
			}
		}
	}
	cout<<dp[n+n][n][n]<<endl;//最终状态存放在终点第一条路在n行,,第二条路在n行。
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值