首页 > 其他分享 >P1004-DP【绿】

P1004-DP【绿】

时间:2023-12-09 13:13:39浏览次数:35  
标签:10 int P1004 maxn DP 两人 dp 坐标

这道题很有趣,暴搜的时间复杂度太过于凶残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;
}

以上、

标签:10,int,P1004,maxn,DP,两人,dp,坐标
From: https://www.cnblogs.com/gongkai/p/17890794.html

相关文章

  • P1854-DP【绿】
    首先通过这道题我收获了一个知识,那就是deque可以直接赋值,作用和vector类似就是复制一个一摸一样的deque,很好用,越来越发现deque眉清目秀了起来。以后deque可能是我最常用的STL结构了。毕竟queue、stack都用deque来实现明显更方便而且不会多占用什么空间的。一眼便能看出,这道题用记......
  • P1541-DP【绿】
    刚开始理解错题意了,题中说“玩家每次需要从所有的爬行卡片中选择一张之前没有使用过的爬行卡片”指的是不能用同一张卡片,我给理解成不能连续用同一种卡片了。后来想想其实题目中的说法歧义不大,是我粗心才导致看错的。最终我看错的导致了题目难度更高一些,偏偏写完了更高难度的题之......
  • 既然UDP更快,为啥这么多年一直用TCP ?
    你们好啊,我是老杨。有点基本技术常识的粉丝朋友都知道,UDP肯定是比TCP快的。很多人对TCP和UDP的了解很浅,直到自己真的经历了一些通信项目之后,你才会愿意根据实际情况埋头苦学,企图“速成”一下。要是问你为什么快,我相信大多数人,也是能从各个角度,说上几句有的没的。但是,既然如此,为什么......
  • centos安装xrdp服务,可以使用系统用户mstsc连接
    Centos6安装依赖yuminstall-yautoconfautomakelibtoolpkg-configopenssl-develpam-devellibjpeg-develfuse-develTurboJPEGlibX11-devellibXfixes-devellibXrandr-develnasmbinutilsredhat-lsb-coreCentos7安装依赖yuminstall-yfingercmakepatchgccma......
  • 构建用于复杂数据处理的高效UDP服务器和客户端
    title:构建用于复杂数据处理的高效UDP服务器和客户端banner_img:https://cdn.studyinglover.com/pic/2023/12/334c0c129076533308cbc7e03f8c55be.pngdate:2023-12-723:03:00tags:-踩坑构建用于复杂数据处理的高效UDP服务器和客户端引言在当今快速发展的网络通信世界......
  • P1725-DP【绿】
    这道题最开始我用记搜写的,然后WA了一些点,后来看了半天才发现是数组开小了,原来他给了两个数据范围,一个是60%数据的数据范围,另一个是100%数据的数据范围。我没仔细看,没看见后面那行,把60%数据当成本题数据范围了....自然WA了(不过有点好奇为什么不是RE,但是不重要,这种情况不罕见)然后,增......
  • 如何在CentOS7 安装 XRDP 远程桌面服务器
    1)图形界面安装CentOS7没有图形化操作可能对很多人来说都不太习惯,下面我们来为CentOS7安装图形化界面,本文以安装GNOME图形化为例**写在安装前:**如果你的CentOS7是最小化安装,默认都是不带XWINDOWS的配置公网Yum源mkdir/etc/yum.repos.d/backupmv/etc/yum.repo......
  • 树的中心——树形dp/换根dp启蒙
    请你在树中找到一个点,使得该点到树中其他结点的最远距离最近。这个点被称为树的中心。题解:https://www.cnblogs.com/dx123/p/17302104.html评测:https://www.acwing.com/problem/content/1075/暴力做法是以每个点为根,求出从根向下走的最远距离,这个过程需要做n遍,每一遍dfs的复杂......
  • 网络通信、UDP通信、TCP通信、BS架构模拟、URL了解
    网络编程可以让程序与网络上的其他设备中的程序进行数据交互所以,我们学习网络编程的主要目的就是为了实现网络通信网络通信网络通信基本模式常见的通信模式有如下2种形式:Client-Server(Cs)、Browser/Server(Bs)Client-Server(Cs)主要是客户端与服务端之间的联系(就是相应的App和后......
  • 树的直径——树形dp求法
    树上任意两节点之间最长的简单路径即为树的「直径」。树形DP的做法可以在存在负权边的情况下求解出树的直径。constintN=10010,M=20010;intn,a,b,c,ans;structedge{intv,w;};vector<edge>e[N];intdfs(intx,intfa){intd1=0,d2=0;for(autoed:e[x]){......