这道题很有趣,暴搜的时间复杂度太过于凶残O(K*(2^n)^2)(K的意思是大常数),不过作为提高组T4,这道题数据范围太小了,感觉哪怕是离谱的暴搜也能过。

再加上一时半会没想好多项式时间复杂度的正解DP,就搞了一个四不像出来,第一次走用搜索来实现第二次走用记搜来实现,这样时间复杂度就是O((2^n)*(n^2)),仍然很凶残但毕竟数据太水了。这个做法很简单,对于现在的我来说简直是基本功了,五十行代码很快便写好然后轻松调了调就AC了

但显然我还是要想想正解的,初步想了一下没想出来便看了眼题解,没看懂题解的思路讲解但是看了眼代码后,瞬间想到了以下内容便理解了整个过程。

此前考虑到第一次搜索会影响第二次搜索而第一次搜索后的结果用状态来描述就要用n个坐标这会导致dp的时间复杂度变为n^n从而使得dp毫无意义。

但是,后来意识到如果同步处理两次移动,用一个四个坐标(即两人坐标)的dp来刻画一个状态,这是他们走的第几步即他们所在那一圈这两个数据显然都隐含在坐标中而且由于状态转移过程中不会改变两人总步数的差且结尾状态两人总步数的差是0!!!这就导致我需要求的那部分的dp两人总步数的差始终为0!!!也就是说两人始终走过总路程相同,他们在同一条“带”上,这意味着根本不需要存某个人走过了哪些步来一一对照,只需要在每一步考虑他们是否在同一带上选择了同一格即可!如果选择了同一格,那去掉重复加了的得分即可。

甚至,由于两人总路程相同,而总路程+两人x坐标可以推导出两人y坐标,所以用总路程+两个x坐标就可以足以刻画状态,就这般,三维DP即可解决问题!

妙哉

思路已经完全清晰,没什么可说的了,也没什么浪费时间写出来的必要了,毕竟想明白以上内容后想写简直太简单了,在这里复制一段别人写的四维dp代码和三维dp代码,仅供参考。

O((2^n)*(n^2))-Code

#include <iostream>
#include <cstring> using namespace std;
int ans,dp[10][10],N,x,y,z,a[10][10],b[10][10];
int dpdfs(int x,int y)
{
if(x<1||y<1)return -99999999;
if(x==1&&y==1)return dp[1][1]=0;
if(dp[x][y]!=-1)return dp[x][y];
int DFS=max(dpdfs(x-1,y),dpdfs(x,y-1));
if(b[x][y]==0)DFS+=a[x][y];
return dp[x][y]=DFS;
}
void dfs(int x,int y,int l)
{
if(x>N||y>N)return;
if(x==N&&y==N)
{
memset(dp,-1,sizeof(dp));
ans=max(ans,l+dpdfs(N,N));
return;
}
b[x+1][y]=1;dfs(x+1,y,l+a[x+1][y]);b[x+1][y]=0;
b[x][y+1]=1;dfs(x,y+1,l+a[x][y+1]);b[x][y+1]=0;
return;
} int main()
{
cin>>N;
while(cin>>x>>y>>z)
{
if(x==0&&y==0&&z==0) break;
a[x][y]=z;
}
b[1][1]=1;
dfs(1,1,a[1][1]);
cout<<ans<<endl;
return 0;
}

O(n^4)-Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=10;
int a[maxn][maxn],f[maxn<<1][maxn][maxn],n;
int main()
{
scanf("%d",&n);
memset(a,0,sizeof(a));
while (1)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
if (x==0 && y==0 && z==0) break;
a[x][y]=z;
}
f[0][1][1]=a[1][1];//初始化
for (int i=1;i<=2*n-2;i++)//因为最多走2n-2步,x1+x2=i+2
for (int x1=1;x1<=n;x1++)
for (int x2=1;x2<=n;x2++)
{
int y1=i+2-x1,y2=i+2-x2;//算出纵坐标
if (y1<1 || y2<1) continue;//判断是否越界
f[i][x1][x2]=max(f[i-1][x1][x2],max(f[i-1][x1-1][x2],max(f[i-1][x1][x2-1],f[i-1][x1-1][x2-1])))+a[x1][y1]+a[x2][y2];//上面说的转移
if (x1==x2 && y1==y2) f[i][x1][x2]-=a[x1][y1]; //如果走到同一个点就减一次
}
printf("%d",f[n*2-2][n][n]);//目标状态
return 0;
}

O(n^3)-Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=10;
int a[maxn][maxn],f[maxn<<1][maxn][maxn],n;
int main()
{
scanf("%d",&n);
memset(a,0,sizeof(a));
while (1)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
if (x==0 && y==0 && z==0) break;
a[x][y]=z;
}
f[0][1][1]=a[1][1];//初始化
for (int i=1;i<=2*n-2;i++)//因为最多走2n-2步,x1+x2=i+2
for (int x1=1;x1<=n;x1++)
for (int x2=1;x2<=n;x2++)
{
int y1=i+2-x1,y2=i+2-x2;//算出纵坐标
if (y1<1 || y2<1) continue;//判断是否越界
f[i][x1][x2]=max(f[i-1][x1][x2],max(f[i-1][x1-1][x2],max(f[i-1][x1][x2-1],f[i-1][x1-1][x2-1])))+a[x1][y1]+a[x2][y2];//上面说的转移
if (x1==x2 && y1==y2) f[i][x1][x2]-=a[x1][y1]; //如果走到同一个点就减一次
}
printf("%d",f[n*2-2][n][n]);//目标状态
return 0;
}

以上、

P1004-DP【绿】的更多相关文章

  1. 「疫期集训day4」硝烟

    那真是一阵恐怖的炮击(that boomed booms),响亮的炮音(that noise),滚滚的硝烟(that smoke),熊熊的火焰在围绕着我们前进...小心前进(go and be car ...

  2. 洛谷 P1004 方格取数 【多进程dp】

    题目链接:https://www.luogu.org/problemnew/show/P1004 题目描述 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 ...

  3. 洛谷 - P1004 - 方格取数 - 简单dp

    https://www.luogu.org/problemnew/show/P1004 这道题分类到简单dp但是感觉一点都不简单……这种做两次的dp真的不是很懂怎么写.假如是贪心做两次,感觉又不能证明 ...

  4. 棋盘DP三连——洛谷 P1004 方格取数 &&洛谷 P1006 传纸条 &&Codevs 2853 方格游戏

    P1004 方格取数 题目描述 设有N $\times N$N×N的方格图(N $\le 9$)(N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字00.如下图所示(见样例): A ...

  5. P1004 方格取数(四维dp)

    P1004 方格取数 思路如下 这题是看洛谷大佬的思路才写出来的,所以我会把大佬的思路展示如下: 1⃣️:我们可以找到一个叫思维dp的东西,dp[i][j][k][l],其中前两维表示一个人从原点出发 ...

  6. P1004 方格取数——奇怪的dp

    P1004 方格取数 题目描述 设有 \(N\times N\) 的方格图 \((N\leq 20)\),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字 \(0\) .如下图所示(见样例) ...

  7. 洛谷P1004 方格取数-四维DP

    题目描述 设有 N \times NN×N 的方格图 (N \le 9)(N≤9) ,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字 00 .如下图所示(见样例): A 0 0 0 0 0 ...

  8. Luogu P1004/P1006 方格取数/传纸条 【棋盘Dp】 By cellur925

    我明明记得写过这篇啊qwq为什么会搞丢 两题几乎一样. 如果再拓展到k条路,就要用网络流跑了,本蒟现在还不会. 我们容易想到四维dp,但是有一种更好的方法. 首先,先从左上到右下.再从右下到左上可以近 ...

  9. P1004 方格取数[棋盘dp]

    题目来源:洛谷 题目描述 设有N×N的方格图(N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0.如下图所示(见样例): A 0 0 0 0 0 0 0 0 0 0 13 0 0 ...

  10. 洛谷 P1004 方格取数 【多线程DP/四维DP/】

    题目描述(https://www.luogu.org/problemnew/show/1004) 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 人数字0. ...

随机推荐

  1. 基于python人脸识别考勤系统(语音播报)

    介绍: 本项目是大二寒假在家没事写的,一直没有时间讲本项目分享出来,现在有时间了哈.那就让我简单的将项目介绍一下吧.好了废话不多说了,直接上图 初始化界面: 可以看到所有的功能都展现在了左边的功能栏中 ...

  2. Volcano 原理、源码分析(一)

    0. 总结前置 1. 概述 2. Volcano 核心概念 2.1 认识 Queue.PodGroup 和 VolcanoJob 2.2. Queue.PodGroup 和 VolcanoJob 的关 ...

  3. Windows Server 2016 Standard RemoteApp应用发布配置举例

    RemoteApp 应用发布介绍 RemoteApp 是微软在Windows Server 2008 之后,在其系统中集成的一项服务功能,用户可以通过远程桌面访问远端服务器的桌面与程序,客户端本机在无 ...

  4. Redis 分片集群

    1.Redis分片集群 1.1.搭建分片集群 主从和哨兵可以解决高可用.高并发读的问题.但是依然有两个问题没有解决: 海量数据存储问题 高并发写的问题 使用分片集群可以解决上述问题,如图: 分片集群特 ...

  5. SQL语句(mysql)「一」

    SQL的一些常用语句 创建类 CREAT DATABASE <数据库名>; 该方法创建一个数据库,当要使用一个数据库的时候,使用指令: USE <数据库名>; 查看当前正在使用 ...

  6. jumpserver连接ecs实例报错:UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh_exchange_identification: Connection closed by remote host", "unreachable": true

    报错分析思路: 1.是ssh密钥设置有没有对接 2.防火墙拦截问题 3.用户设置问题 4.sshd配置问题 问题解决: 无法与221.229.216.39端口35846进行协商:找不到匹配的主机密钥类 ...

  7. 如何快速部署本地训练的 Bert-VITS2 语音模型到 Hugging Face

    Hugging Face是一个机器学习(ML)和数据科学平台和社区,帮助用户构建.部署和训练机器学习模型.它提供基础设施,用于在实时应用中演示.运行和部署人工智能(AI).用户还可以浏览其他用户上传的 ...

  8. Spring Cloud Eureka 服务注册中心怎么配置

    「Spring Cloud Eureka 入门系列」 Spring Cloud Eureka 入门 (一)服务注册中心详解 Spring Cloud Eureka 入门 (二)服务提供者详解 Spri ...

  9. Java 给PPT中的表格设置分布行和分布列

    在表格中可设置"分布行"或"分布列"将行高.列宽调整为协调统一的高度或宽度,是一种快速实现表格排版的方法之一.下面,通过Java后端程序代码介绍如何在PPT幻灯 ...

  10. Multi-Architecture镜像制作指南已到,请查收!

    摘要:使用Multi-Architecture镜像,可以让docker根据系统架构去拉取对应的镜像,服务的部署脚本等可以在不同架构的系统间使用相同的配置,减化服务配置,提高了服务在不同系统架构间的一致 ...