【蓝桥每日一题]-动态规划 (保姆级教程 篇11)#方格取数2.0 #传纸条

news/2024/7/20 20:14:44 标签: 动态规划, 深度优先, 算法

目录

题目:方格取数

  思路: 

题目:传纸条

  思路: 


   

题目:方格取数

  (跑两次)

     

思路: 

   

如果记录一种方案后再去跑另一个方案,影响因素太多了,所以两个方案要同时开跑。

   

我们设置 f[x][y][x2][y2]当第一种方案走到x,y ,第二种方案走到x2,y2时取得的最大数。

要注意不要重复取数,也即是两种方案同时走到了同一个格子,这种情况要去重。

    

然后就是递归方程: 

if (x<N&&x2<N) M=max(M,dfs(x+1,y,x2+1,y2)+s[x+1][y]+s[x2+1][y2]-s[x+1][y]*(x+1==x2+1&&y==y2));//都向下走,如果有重复,减去重复
if (x<N&&y2<N) M=max(M,dfs(x+1,y,x2,y2+1)+s[x+1][y]+s[x2][y2+1]-s[x+1][y]*(x+1==x2&&y==y2+1));//方案1向下,2向右
if (y<N&&x2<N) M=max(M,dfs(x,y+1,x2+1,y2)+s[x][y+1]+s[x2+1][y2]-s[x][y+1]*(x==x2+1&&y+1==y2));//方案1向右,2向下
if (y<N&&y2<N) M=max(M,dfs(x,y+1,x2,y2+1)+s[x][y+1]+s[x2][y2+1]-s[x][y+1]*(x==x2&&y+1==y2+1));//都向右走

也就是dfs(x,y,x2,y2)可以向下下,下右,右下,右右四种情况递归。

#include<iostream> 
using namespace std; //流水的动归,铁打的递推
int N=0;
int s[15][15],f[11][11][11][11];
int dfs(int x,int y,int x2,int y2)
{
    if (f[x][y][x2][y2]!=-1) return f[x][y][x2][y2];//记忆化
    if (x==N&&y==N&&x2==N&&y2==N) return 0;//如果两种方案都走到了终点,返回结束 
    int M=0;
    if (x<N&&x2<N) M=max(M,dfs(x+1,y,x2+1,y2)+s[x+1][y]+s[x2+1][y2]-s[x+1][y]*(x+1==x2+1&&y==y2));//都向下走,如果有重复,减去重复
    if (x<N&&y2<N) M=max(M,dfs(x+1,y,x2,y2+1)+s[x+1][y]+s[x2][y2+1]-s[x+1][y]*(x+1==x2&&y==y2+1));//方案1向下,2向右
    if (y<N&&x2<N) M=max(M,dfs(x,y+1,x2+1,y2)+s[x][y+1]+s[x2+1][y2]-s[x][y+1]*(x==x2+1&&y+1==y2));//方案1向右,2向下
    if (y<N&&y2<N) M=max(M,dfs(x,y+1,x2,y2+1)+s[x][y+1]+s[x2][y2+1]-s[x][y+1]*(x==x2&&y+1==y2+1));//都向右走
    f[x][y][x2][y2]=M;//记录这种情况 
    return M;//返回最大值 
}
int main()
{
    int x,y,t;cin>>N;
    for(int a=0;a<=N;a++)//不能memset了,必须初始化成-1,否则dfs会死循环
      for(int b=0;b<=N;b++)
        for(int c=0;c<=N;c++)
          for(int d=0;d<=N;d++) f[a][b][c][d]=-1;
	while(cin>>x>>y>>t&&(x+y+t))s[x][y]=t;
    cout<<dfs(1,1,1,1)+s[1][1];//输出,因为dfs中没有考虑第一格,即s[1][1],所以最后要加一下 
    return 0;
}

   

题目:传纸条

     

    

思路: 

一样的思路,要同时开始跑才行。

   

f[x1][y1][x2][y2]表示走到两个方案分别走到(x1,y1)(x2,y2)的最优解,因为两个方案走的哈曼顿距离是一样的,可以优化成f[k][x1][x2]表示走到(x1,k-x1)(x2,k-x2)的最优解。

     
转移方程:f(k,x1,x2)=max{f(k-1,x1,x2),f(k-1,x1,x2-1),f(k-1,x1-1,x2),f(k-1,x1-1,x2-1)},分别为来自左左,左上,上左,上上,然后减去重复即可。

    
注意:1,两个人不能走同一个格子,所以x1!=x2     
           2,1<=k-x1<=m;故 x1<=k-1且x1>=k-m  同理x2<=k-1且x2>=k-m
 

     

#include<bits/stdc++.h>
using namespace std;
const int N = 55;
int n, m;
int g[N][N];
int f[N*2][N][N];
int main()
{
    scanf("%d%d", &n, &m);
    for (int i=1; i<=n; i++)
    for (int j=1; j<=m; j++){
        scanf("%d", &g[i][j]);
	}
    for (int k=2; k<=n+m; k++)
    for (int x1=max(1,k-m); x1<=min(k-1,n); x1++)
    for (int x2=max(1,k-m); x2<=min(k-1,n); x2++){
    	int t=g[x1][k-x1];//当前好心度
    	if(x2!=x1) t+=g[x2][k-x2];
    	for (int a=0; a<=1; a++)
    	for (int b=0; b<=1; b++){
    		f[k][x1][x2]=max(f[k][x1][x2],f[k-1][x1-a][x2-b]+t);
		}
	}
    printf("%d\n", f[n+m][n][n]);
    return 0;
}


http://www.niftyadmin.cn/n/5115639.html

相关文章

【C++】继承 ⑧ ( 继承 + 组合 模式的类对象 构造函数 和 析构函数 调用规则 )

文章目录 一、继承 组合 模式的类对象 构造函数和析构函数调用规则1、场景说明2、调用规则 二、完整代码示例分析1、代码分析2、代码示例 一、继承 组合 模式的类对象 构造函数和析构函数调用规则 1、场景说明 如果一个类 既 继承了 基类 ,又 在类中 维护了一个 其它类型 的…

解释C++中成员函数的前面或后面加一个const各是什么意思

解释C中成员函数的前面或后面加一个const各是什么意思 成员函数的前面加一个const&#xff0c;表示函数的返回值是const类型&#xff0c;也就是不能被修改。例如&#xff0c;const char * getname ()表示这个函数返回一个指向const字符的指针&#xff0c;不能通过这个指针修改字…

地图金字塔所在块的经纬度范围

地图金字塔所在块的经纬度范围 算法 地图金字塔从第0层开始 #define LON_SPAN 360.0 // 开始经度(最左端) #define LAT_SPAN 180.0 #define GLOBAL_LEFT -180.0 // 开始纬度(最上端) #define GLOBAL_TOP 90.0 #define GLOBAL_RIGHT 180.0 #define GLOBAL_BOTTOM -90.0 // 地球…

imu预积分学习(更新中)

imu预积分学习&#xff08;更新中&#xff09; IMU预积分可以做什么&#xff1f; 以上面那个经典图片为例子&#xff0c;IMU可以通过六轴数据&#xff0c;拿到第i帧和第j帧之间的相对位姿&#xff0c;这样不就可以去用来添加约束了吗 但是有一个比较大的问题是&#xff1a; I…

UG NX二次开发(C#)-采用NXOpen完成对象的合并操作

文章目录 1、前言2、Ufun实现布尔和操作的函数2.1 函数说明2.2 源代码3、采用NXOpen实现布尔和操作的函数3.1 函数说明3.2 源代码4、测试结果4.1 采用UFun 与NXOpen的结果4.2采用UFun 与NXOpen的对比说明1、前言 在UG NX中开发过程中,创建特征对象的时候往往会用到布尔操作,…

NVIDIA大力推动DPU“出圈”,搅动中国AI基础设施市场

自大模型AI横扫全球以来&#xff0c;DPU数据处理器越来越为人所熟知。作为AI数据中心基础设施的新三驾马车之一&#xff0c;DPU与CPU和GPU共同支撑起了大模型AI的加速计算需求。从2020年开始&#xff0c;NVIDIA创始人兼CEO黄仁勋就在公开场合不断强调&#xff0c;DPU将成为未来…

Java 中是如何获取 IP 属地的

随着互联网的普及&#xff0c;人们在使用计算机或移动设备上网时&#xff0c;都会被分配一个IP地址&#xff0c;以便进行网络通信。而当我们访问某个网站或使用某些网络服务时&#xff0c;我们通常会发现不同地区的用户会显示不同的IP属地。那么&#xff0c;在Java中是如何获取…

linux驱动开发学习001:概述

linux的内核源码编译后&#xff0c;会生成一个总的镜像。镜像加载到内存中运行他&#xff0c;就会启动内核。驱动属于内核代码的一部分&#xff0c;对驱动修改要重编整个内核&#xff0c;麻烦但驱动可以独立于内核镜像外&#xff0c;并能动态加载和卸载字符设备驱动&#xff0c…