2021-06-19

2021/06/19模拟 - 书上例题*2

T1方格取数

在这里插入图片描述如图的图:

很显然的一道动态规划题目
策略:四重循环表示从x1到y1的最大值+x2到y2的最大值
注意:不能重复走!
所以状态转移方程:
sum[x1][y1][x2][y2] = max(max(sum[x1-1][y1][x2][y2-1],sum[x1][y1-1][x2-1][y2]),max(sum[x1-1][y1][x2-1][y2],sum[x1][y1-1][x2][y2-1]))+MAP[x2][y2]+MAP[x1][y1];
if(x1 == x2 && y1 == y2)sum[x1][y1][x2][y2] -= MAP[x2][y2];

#include<cstdio>
#include<iostream>
#include<string>
#include<algorithm>
#include<cstring>
#define ll long long
#define SZJ_IN freopen("Pane.in","r",stdin)
#define SZJ_OUT freopen("Pane.out","w",stdout)
using namespace std;
const int MAXN = 51;
ll MAP[MAXN][MAXN];
ll sum[MAXN][MAXN][MAXN][MAXN];
ll n;
int main(){
	//SZJ_IN;SZJ_OUT;
	memset(sum,0,sizeof(sum));
	memset(MAP,0,sizeof(MAP));
	scanf("%lld",&n);
	for(int kk = 1 ; ; kk++){
		ll i,j,num; // i行j列,num
		scanf("%lld %lld %lld",&i,&j,&num);
		if(i==0&&j==0&&num==0)break; 
		MAP[i][j] = num;
	}
//	for(int x1 = 1 ; x1 <= n ; x1++){
//		for(int y1 = 1 ; y1 <= n ; y1++){
//			for(int x2 = 1 ; x2 <= x1 ; x2++){
//				for(int y2 = 1 ; y2 <= y1 ; y2++){
//					if(sum[x1][y1][x2][y2] <= sum[x1-1][y1][x2][y2]){
//						sum[x1][y1][x2][y2] = max(sum[x1][y1][x2][y2],sum[x1-1][y1][x2][y2]+MAP[x1-1][y1]);
//					}
//					if(sum[x1][y1][x2][y2] <= sum[x1][y1-1][x2][y2]){
//						sum[x1][y1][x2][y2] = max(sum[x1][y1][x2][y2],sum[x1][y1-1][x2][y2]+MAP[x1][y1-1]);
//					}
//					if(sum[x1][y1][x2][y2] <= sum[x1][y1][x2-1][y2]){
//						sum[x1][y1][x2][y2] = max(sum[x1][y1][x2][y2],sum[x1][y1][x2-1][y2]+MAP[x2-1][y2]);
//					}
//					if(sum[x1][y1][x2][y2] <= sum[x1][y1][x2][y2-1]){
//						sum[x1][y1][x2][y2] = max(sum[x1][y1][x2][y2],sum[x1][y1][x2][y2-1]+MAP[x2][y2-1]);
//					}
//				}
//			}
//		}
//	}
	for(int x1 = 1 ; x1 <= n ; x1++){
		for(int y1 = 1 ; y1 <= n ; y1++){
			for(int x2 = 1 ; x2 <= n ; x2++){
				for(int y2 = 1 ; y2 <= n ; y2++){
					sum[x1][y1][x2][y2] = max(max(sum[x1-1][y1][x2][y2-1],sum[x1][y1-1][x2-1][y2]),max(sum[x1-1][y1][x2-1][y2],sum[x1][y1-1][x2][y2-1]))+MAP[x2][y2]+MAP[x1][y1];
					if(x1 == x2 && y1 == y2)sum[x1][y1][x2][y2] -= MAP[x2][y2];
				}
			}
		}
	}
//	for(int i = 1 ; i <= n ; i++){
//		for(int j = 1 ; j <= n ; j++){
//			printf("%lld ",MAP[i][j]);
//		}
//		printf("\n");
//	}
	printf("%lld",sum[n][n][n][n]);
	return 0;
}
/*
INSERT: 
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

ANS: 
67
*/

中间的注释是另一种gg在题目中说的4层if判断?!

T2橱窗布置

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
首先审题:
1.题目中I<J那么I的花就必须放在J的左侧,那么可以直接使用记忆化搜索 (暴力) 每次枚举一层,从上一层便利到的点的右边进行下一次便利,边界直接return
2.所谓记忆化搜索都可以用DP解决,不错的↓
DP:
1.dp定义:用dp[i][j]表示1-i束花放到j花瓶的最大值
2.状态转移方程:dp[i][j] = max(dp[i-1][k-1]+a[i][k]),i<=k<=j

#include<cstdio>
#include<iostream>
#include<string>
#include<algorithm>
#include<cstring>
#define ll long long
#define SZJ_IN freopen("flower.in","r",stdin)
#define SZJ_OUT freopen("flower.out","w",stdout)
using namespace std;
const int MAXF = 110,MAXV = 110;
ll f,v;
ll a[MAXF][MAXV];
ll dp[MAXF][MAXV];
//bool vis[MAXV];
//int DP(int F,int k){
//	for(int i = F ; i <= f ; i++){
//		sum[F] = max(sum[F],sum[F]+DP(F+1,i));
//	}
//}
void print(int i,int j){
  	int n;
  	if(i > 0){
    	n = i;
      	while(dp[i][n]!=j){
    		n++;
    	}
      	print(i-1,j-a[i][n]);
      	printf("%d ",n);
    }  
}
int main(){
	//SZJ_IN;SZJ_OUT;
	memset(dp,0,sizeof(dp));
	scanf("%lld %lld",&f,&v);
	for(int i = 1 ; i <= f ; i++){
		for(int j = 1 ; j <= v ; j++){
			scanf("%lld",&a[i][j]);
		}
	}
	for(int i = 1 ; i <= v ; i++){
		dp[1][i] = a[1][i];
	}
	for(int i = 1 ; i <= f ; i++){
		for(int j = i ; j <= v-f+i ; j++){
			for(int k = i ; k <= j ; k++){
				dp[i][j] = max(dp[i][j],dp[i-1][k-1]+a[i][k]);
			}
		}
	}
	printf("%lld\n",dp[f][v]);
	print(f,dp[f][v]);
//	print(f,v);
//	for(int i = 1 ; i <= f ; i++){
//		for(int j = 1 ; j <= v ; j++){
//			printf("%lld ",a[i][j]);
//		}
//		printf("\n");
//	}
//	DP(1,1);
	return 0;
}
/*
INSERT:
3 5
7 23 -5 -24 16
5 21 -4 10 23
-21 5 -4 -20 20

ANS:
53
2 4 5
*/

输出:

void print(int i,int j){
  	int n;
  	if(i > 0){
    	n = i;
      	while(dp[i][n]!=j){
    		n++;
    	}
      	print(i-1,j-a[i][n]);
      	printf("%d ",n);
    }  
}

觉得gg今天在diss我,所以以后要多注意基础
不要抢AC(滑稽)
✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值