首页 > 其他分享 >坐标DP

坐标DP

时间:2024-02-17 16:36:44浏览次数:26  
标签:cnt int 代码 坐标 三角形 DP

坐标DP相较来说会比较简单。
直接上例题

1.坐标遍历问题
传纸条

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=120;
int m,n;
int g[N][N],f[N][N][N];
int ans;
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>g[i][j];
		}
	}
	for(int k=2;k<=n+m-1;k++)
	{
		for(int i1=1;i1<=n;i1++)
		{
			for(int i2=1;i2<=n;i2++)
			{
				int j1=k+1-i1;
				int j2=k+1-i2;
				if(j1<1||j2<1)
				{
					continue;
				}
				if(i1==i2)
				{
					continue;
				}
				ans=max(f[k-1][i1-1][i2-1],f[k-1][i1-1][i2]);
				ans=max(ans,f[k-1][i1][i2-1]);
				
				f[k][i1][i2]=max(ans,f[k-1][i1][i2])+g[i1][j1]+g[i2][j2];
								 
			}
		}
	}
	cout<<f[n+m-2][n][n-1];
}
这是优化后的代码,其中k代表的是步数,根据题易知从左上到右下所需步数总共为m+n-1,同样我们只需知道步数和它的横坐标,就可以求出它的纵坐标,因此我们只需记录三个变量就可以得到结果。

2.构成问题
接下来是坐标DP比较重要的题型,构成问题。

三角蛋糕

首先它想要构成2层正三角形,就需要它下面三个三角形没坏,想要构成3层正三角形就需要它每个下面的下面三个三角形没坏,以此类推,我们只需要遍历时为能构成多层的正三角形标记,只要它下面三个三角形没坏,就标记成1,如果它下面的三个三角形都标记成1就给它标记成2(注意三个三角形标记数可能不同,要取最小)。这就是代码的底层逻辑。
接下来就是处理一下细节,一个是正序遍历倒着的三角形,倒序遍历正着的三角形,同时注意作为顶的三角形正倒情况。好了,剩下的就没什么了,看代码吧。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=3000; 
int n,ans,cnt; 
char g[N][N];
int f[N][N],c[N][N];
int main()
{
    cin>>n;
	for(int i=1;i<=N-1;i++)
	{
		for(int j=1;j<=N-1;j++)
		{
			g[i][j]='1';
		}
	 } 
	 
    for(int i=1;i<=n;i++)
    {
    	for(int j=i;j<=(n-i)*2+i;j++)
    	{
    		
			cin>>g[i][j];
			if(g[i][j]=='1')
			{
				cnt++;
			}
		}
	}
	if(cnt==n*(n*2)/2)
	{
		cout<<0;
		exit(0);
	}
	for(int i=1;i<=n;i++)
    {
    	for(int j=i;j<=(n-i)*2+i;j++)
    	{
				if(g[i][j]=='0'&&g[i-1][j-1]=='0'&&g[i-1][j]=='0'&&g[i-1][j+1]=='0')
				{
//					cout<<i<<" "<<j; 
					int num=0x3f3f3f3f;
					num=min(f[i-1][j-1],num);
					num=min(f[i-1][j],num);
					num=min(f[i-1][j+1],num);
					f[i][j]=max(f[i][j],num+1);
				}		
		}
	}
	for(int i=n;i>=1;i--)
    {
    	for(int j=i;j<=(n-i)*2+i;j++)
    	{
				if(g[i][j]=='0'&&g[i+1][j-1]=='0'&&g[i+1][j]=='0'&&g[i+1][j+1]=='0')
				{
					int num=0x3f3f3f3f;
					num=min(c[i+1][j-1],num);
					num=min(c[i+1][j],num);
					num=min(c[i+1][j+1],num);
					c[i][j]=max(c[i][j],num+1);
				}		
		}
	}
	for(int i=1;i<=n;i++)
    {
    	for(int j=i;j<=(n-i)*2+i;j++)
    	{
    		if((j-i+1)&1)
    		{
//    			cout<<i<<" "<<j<<" ";
    			ans=max(ans,f[i][j]);
			}
			if((j-i+1)%2==0)
			{
				ans=max(ans,c[i][j]);
			}
		}
//		cout<<endl;
	}
//	cout<<ans<<" ";
	int s=(ans+1)*(1+(ans+1)*2-1)/2;
	cout<<s;
}

盖房子

(同上)不详细解析了

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=3000; 
int n,m,ans,cnt;
int g[N][N],f[N][N];
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
    	for(int j=1;j<=m;j++)
    	{
    		cin>>g[i][j];
    		if(g[i][j]==0)
    		{
    			cnt++;
			}
		}
	}
	if(cnt==n*m)
	{
		cout<<0;
		exit(0);
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(g[i][j]==1&&g[i][j-1]==1&&g[i-1][j]==1&&g[i-1][j-1]==1)
			{
				int num=0x3f3f3f3f;
				num=min(num,f[i][j-1]);
				num=min(num,f[i-1][j]);
				num=min(num,f[i-1][j-1]);
				f[i][j]=max(num+1,f[i][j]);
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			ans=max(ans,f[i][j]);
		}
	}
	cout<<ans+1;
}

标签:cnt,int,代码,坐标,三角形,DP
From: https://www.cnblogs.com/zhengchenxi/p/18018064

相关文章

  • 关于动态规划(Dynamic Programming)的若干思考 ------ [2.线性dp]
    线性dp的两个经典题目:最长上升子序列(LIS)and最长公共子序列(LCS)1.LIS核心代码#include<bits/stdc++.h>usingnamespacestd;constintmaxn=2024;intcnt=0,ans=1;intf[maxn],a[maxn],c[maxn];voidout(intx){ if(x==0)return; out(c[x]); cout<<a[x]<<......
  • 线性dp
    基本应用:最长上升子序列:题目描述设有由n个不相同的整数组成的数列,记为:b(1)、b(2)、……、b(n)且b(i)<>b(j)(i<>j),若存在i1<i2<i3<…<ie且有b(i1)<b(i2)<…<b(ie)则称为长度为e的不下降序列。程序要求,当原数列出之后,求出最长的上升序列。例如13,7,9,16,38,24,37,18,44,19,21,22,63......
  • dp总结(背包,线性,区间,坐标,树形)
    背包dp0/1背包这种背包会提供可选的物品,背包的容积以及每件物品的价值,并且在选择物品是每件物品只有选一件或不选两种状态。例题输入4512243445输出8二维解法代码//状态转移方程为:f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i])#include"bits/stdc++.h"using......
  • 坐标dp
    坐标dp典型例题:传纸条题目描述小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题。一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了。幸运的是,他们可以通过传纸条来进行交流。纸条要经由许多同学传......
  • 线性DP
    这篇主要涉及线性DP。先介绍给模型,求最长上升子序列。点击查看代码#include<bits/stdc++.h>usingnamespacestd;constintN=1020;intn;intf[N],ans,a[N];intpre[N],te;voidoutput(intx){ if(x==0) { return; } output(pre[x]); cout<<a[x]<<"";......
  • 区间dp
    区间dp区间dp属于线性dp的一种,以“区间长度”作为dp的“阶段”,用两个坐标(区间的左、右端点)描述每个维度。区间dp中,一个状态往往由若干个比它更小且包含于它的区间所代表的阶段转移而来,所以区间dp的决策往往就是划分dp的方法。典型例题:石子合并for(inti=1;i<=n;i++)f[i][i]=......
  • 五大基础dp
    动规条件•最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。•无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。•有重叠子问题:即子问题之......
  • 背包dp
    01背包:所谓01背包,就是每种物体有一个价值且数量只有一个,给定一个背包容量,在不超出背包容量的前提下在n个物体中取m个,求最大价值。点击查看代码//f[i]指体积为i时的最大价值for(inti=1;i<=n;i++){//第一层循环是指遍历每种物体,n是物体种数 for(intj=m;j>=v[i];j--){//第......
  • 背包DP
    下面介绍一下背包DP主要题型基础模型(没什么好说的,上模板)1.01背包最主要的模板,应用很多,很重要!!!倒着遍历容积,不会受后选小的f[i][j]影响,已经选过的物品不会再选一遍。点击查看代码#include<bits/stdc++.h>usingnamespacestd;constintN=10020;intf[N];intn,m;intv......
  • 关于动态规划(Dynamic Programming)的若干思考 ------ [1.背包dp]
    背包dp;1.01背包(1)领域展开#include<bits/stdc++.h>//simpleusingnamespacestd;constintmaxm=2024;intn,m;intw[maxm],v[maxm],f[maxm][maxm];intmain(){ cin>>n>>m; for(inti=1;i<=n;i++) cin>>v[i]>>w[i]; for(i......