首页 > 其他分享 >洛谷 P1002 [NOIP2002 普及组] 过河卒

洛谷 P1002 [NOIP2002 普及组] 过河卒

时间:2024-10-24 20:16:56浏览次数:10  
标签:洛谷 NOIP2002 int 路径 P1002 条数 坐标 20 dp

你好,我是gwg725。

洛谷账号:

大号

小号

欢迎与我讨论。:)

题目描述:

棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下、或者向右。同时在棋盘上的某一点有一个对方的马(如C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点,如图3-1中的C点和P1,……,P8,卒不能通过对方马的控制点。棋盘用坐标表示,A点(0,0)、B点(n, m) (n,m为不超过20的整数),同样马的位置坐标是需要给出的,C≠A且C≠B。现在要求你计算出卒从A点能够到达B点的路径的条数。

输入:

给出n、m和C点的坐标。

输出:

从A点能够到达B点的路径的条数。

序言:

好了,题目读完了。这道题是我入门dp第一道关键,也是我独自一人在看了关于dp相关资料下想了半个小时题目,所以我认为这道题极有意义,就写了文章。刚开始的话,我没看你谷的算法标签,莽着写搜索代码,代码是这样子的:

#include<bits/stdc++.h>
using namespace std;
int fx[9]={0,1,1,2,2,-2,-2,-1,-1};
int fy[9]={0,2,-2,1,-1,1,-1,2,-2};
int dx[3]={0,1,0};
int dy[3]={0,0,1};
int n,m;
int mx,my;
bool b[20][20];
int cnt=0;

void dfs(int step,int x,int y)
{
	
	if(x==n&&y==m)
		cnt++;

	b[x][y]=1;
	for(int i=1;i<=2;i++)
	{
		int x_x=dx[i]+x;
		int x_y=dy[i]+y;
		if(x_x>=0&&x_x<=n&&x_y>=0&&x_y<=m&&b[x_x][x_y]==0)
			dfs(step+1,x_x,x_y);
	}
	b[x][y]=0;
}

int main()
{
	cin>>n>>m>>mx>>my;
	for(int i=0;i<=8;i++)
	{
		int xm=fx[i]+mx;
		int ym=fy[i]+my;
		b[xm][ym]=1;
	}
	dfs(0,0,0);
	cout<<cnt;
	
	return 0;
}

 不出所料,只得了60分。当时的我也很蒙圈,第一个问题,就是我的数组开小了。由于从1开始,所以二维数组不能是[20][20],要扩大一点防止数组溢出。

解决完了后,我却还是只有80分,始终改不定,这个时候我才去查看算法标签,这才发现要用坐标dp动态规划。

自那以后,我便开始了dp学习之路。

正文:

我在小学学过一点奥数,知道怎么去算路径条数,所以学坐标dp稍微轻松一点。

没有学过的同学可能很难理解其中的奥妙,所以说我这里做一下解释,请读者朋友耐心看完,这可能对你的学习有很大的作用。

提示:不提倡复制粘贴式题解刷题法,这是自欺欺人的行为,对学习毫无帮助。

我们从最基础的开始解释。

如图,这是一个平面直角坐标系(C++),左上角的坐标为(0,0),右下角的坐标为(2,4)。

上文说道这是一种小奥题目,大体上非常简单。当时的我怎么也不会想到,这东西竟然是一个宏观的坐标型动态规划。(注:这里默认只能走右边或下边)

上图是每一个点从(0,0)可以到达的路径条数,你发现规律了吗?

没错,每一个点从(0,0)可以到达的路径条数为(上面那个点从(0,0)可以到达的路径条数)+(右边那个点从(0,0)可以到达的路径条数)

所以易得动态转移方程式为:

dp\left \{i,j \right \} = dp\left \{i-1,j \right \} +dp\left \{i,j-1 \right \}

与此同时,可得到代码:

#include<bits/stdc++.h>
using namespace std;
int dp[114][114];
int main()
{
	int n,m;
	cin >> n >> m;
	for(int i = 0;i<=n;i++){
		dp[i][0] = 1;
	}
	for(int i = 0;i<=m;i++){
		dp[0][i] = 1;
	}
	for(int i = 1;i<=n;i++){
		for(int j = 1;j<=m;j++){
			dp[i][j] = dp[i-1][j]+dp[i][j-1];
		}
	} 
	cout << dp[n][m];
	return 0;
}

好了,这是一个粗略的路径求过程,现在你应该会了吧?

我们再看回题目,马拦住了过河卒,这不就是把马本身以及它可能回跳到的店遍历一下吗?废话不多说,上代码:

注意!!!!别复制粘贴!!!!你会棕掉

#include<bits/stdc++.h>
#define int long long
using namespace std;
int dp[50][50];
int a[50][50];
int n,m;
int mx,my;
signed main()
{
	scanf("%lld%lld%lld%lld",&n,&m,&mx,&my);
	n++;
	m++;
	mx++;
	my++;
	dp[1][1] = 1;
	for(int i = 1;i<=n;i++){
		for(int j = 1;j<=m;j++){
			if(i == 1&&j == 1) continue;
			if((i == mx&&j == my)||(i == mx+1&&j == my+2)||(i == mx-1&&j == my+2)
			||(i == mx+1&&j == my-2)||(i == mx-1&&j == my-2)||(i == mx-2&&j == my+1)||(i == mx+2&&j == my-1)
			||(i == mx+2&&j == my+1)||(i == mx-2&&j == my-1)) dp[i][j] = 0;
			else dp[i][j] = dp[i-1][j] + dp[i][j-1];
		}
	}
	cout << dp[n][m];
	return 0;					
}

标签:洛谷,NOIP2002,int,路径,P1002,条数,坐标,20,dp
From: https://blog.csdn.net/gwg725/article/details/143212790

相关文章

  • 洛谷 P2680 [NOIP2015 提高组] 运输计划 做题记录
    首先题目要求最大的最小,我们二分答案,对于每个答案,我们筛出比它长的路径,找到它们最长的公共边,删掉后验证正确性即可。找公共边可以用树上差分来做,时间复杂度\(O(m\logn\logV)\),其中\(V\)是二分区间大小。你会发现你挂了一堆点,让我们来卡常:首先预处理出所有节点的\(dfn\),每......
  • 洛谷 P3128 [USACO15DEC] Max Flow P 做题记录
    因为一次添加会对点和边都造成影响,而点一次能加两个,于是最大值一定在点上。由于只有一次询问,考虑树上差分。设一次询问给出的两点为\(x,y\),那么我们在\(x\)和\(y\)处分别加\(1\),在\(\operatorname{lca}(x,y)\)处减\(1\),因为该点本身也有增加,于是我们在它的父节点再减去......
  • 洛谷 P2572 [SCOI2010] 序列操作 做题记录
    其实和小白逛公园差不多,编写代码的难度远大于思路难度,难点是调试:注意在区间异或\(1\)的时候分清代码里的最长连续\(1\)的长度和\(1\)的个数。注意查询最长\(1\)的时候要用结构体上传,如果用到了定值len的话要赋值。注意如果只用一个tag的话,遇到区间异或要对原先......
  • 20241022每日一题洛谷P1223
    普及洛谷P1223接水问题有n个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小第一行为一个整数n,第二行n个整数,第i个整数Ti表示第i个人的接水时间Ti输出两行,第一行为一种平均时间最短的排队顺......
  • 洛谷P3850 [TJOI2007] 书架 splay tree 模板题
    题目链接:https://www.luogu.com.cn/problem/P3850主要操作就是:插入+查询第k值。示例程序:#include<bits/stdc++.h>usingnamespacestd;constintmaxn=1.1e5+5,maxb=20;structNode{ints[2],p,sz;stringname;Node(){}Node(string_n......
  • 洛谷P2596 [ZJOI2006] 书架 题解 splay tree 模板题
    题目链接:https://www.luogu.com.cn/problem/P2596主要涉及的操作就是:找到某一个编号的点(这个操作可以不用splaytree维护)删除某个点将某一个点插入到最前面,最后面,或者某一个位置查询前序遍历为\(k\)的节点编号因为每次删除都会又把这个点加回去,所以可以复用\(n\)个......
  • 洛谷管理员语录(不完整)
    ......
  • P10724 [GESP202406 七级] 区间乘积,洛谷id:sxshm
    题解一、分析看看标签:数论,再看题目:完全平方。这不是质因数分解的标配吗?继续看数据范围:1≤ai......
  • 洛谷 P1197 [JSOI2008] 星球大战 做题记录
    我不会做摧毁,于是反着做,就变成了合并连通块,倒序加边即可,时间复杂度\(O((n+m)\alpha(n))\)。(大抵是吧点击查看代码#include<bits/stdc++.h>#definemem(aqwqawa,bqwqawa)memset((aqwqawa),(bqwqawa),sizeof(aqwqawa))#definem0(aqwqawa)memset((aqwqawa),0,sizeof(aqwqaw......
  • 洛谷题单指南-字符串-P4735 最大异或和
    原题链接:https://www.luogu.com.cn/problem/P4735题意解读:已知长度为n的数组a[],要在l~r范围找到一个p,使得a[p]^a[p+1]^...^a[n]^x最大,求这个最大的异或值。解题思路:1、利用前缀和将问题转化设s[]是a[]的前缀异或数组,要计算a中一段范围l~r的异或,可以借助于s由于s[r]=a[0]^a[......