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

P1002 [NOIP2002 普及组] 过河卒

时间:2024-04-05 22:44:42浏览次数:34  
标签:过河 NOIP2002 int bx LL P1002 check my mx

题目链接:

从起点走到终点,最后一步一定是向右或向下走过来的,因此就可以列出状态转移方程。值得注意的是,对于横着和竖着的两条边界不可直接想当然地认为路径数一定等于 \(1\),因为在中途可能会有控制点的存在,因此还是要老老实实地列出状态转移方程。由于边界时只会从一个方向递推过来,但是初始时下标从 \(1\) 开始导致 \(i=1\) 或 \(j=1\) 时 \(i-1\) 和 \(j-1\) 都是 \(0\),因此也可以直接照搬原本的状态转移方程。

#include <bits/stdc++.h>

using LL = long long;
const int N = 25;
int bx, by, mx, my;
LL f[N][N], s[N][N];

bool check(int x, int y) {//判断马的“控制点”是否合法
	if (x < 1 || x > bx || y < 1 || y > by) return false;
	return true;
}

int main()
{
	std::cin >> bx >> by >> mx >> my;
	bx += 1, by += 1, mx += 1, my += 1;//下标从1开始
	
	s[mx][my] = 1;
	if (check(mx + 2, my + 1)) s[mx + 2][my + 1] = 1;
	if (check(mx + 2, my - 1)) s[mx + 2][my - 1] = 1;
	if (check(mx + 1, my + 2)) s[mx + 1][my + 2] = 1;
	if (check(mx + 1, my - 2)) s[mx + 1][my - 2] = 1;
	if (check(mx - 2, my - 1)) s[mx - 2][my - 1] = 1;
	if (check(mx - 2, my + 1)) s[mx - 2][my + 1] = 1;
	if (check(mx - 1, my - 2)) s[mx - 1][my - 2] = 1;
	if (check(mx - 1, my + 2)) s[mx - 1][my + 2] = 1;
	//将所有合法的控制点标记为真
	
	f[1][1] = 1;//如果起点即终点,那么就无需走,这也算一条路径
	for (int i = 1; i <= bx; i++) {
		for (int j = 1; j <= by; j++) {
			if ((i != 1 || j != 1) && !s[i][j]) f[i][j] = f[i - 1][j] + f[i][j - 1];//如果该位置不是控制点,且横纵坐标至少有一个不是1,即不是起点,就可以从两个方向去递推
		}
	}	
	std::cout << f[bx][by];
	return 0;
}

更易理解的版本:

#include <bits/stdc++.h>

using LL = long long;
const int N = 25;
int bx, by, mx, my;
LL f[N][N], s[N][N];

bool check(int x, int y) {
	if (x < 1 || x > bx || y < 1 || y > by) return false;
	return true;
}

int main()
{
	std::cin >> bx >> by >> mx >> my;
	bx += 1, by += 1, mx += 1, my += 1;
	
	s[mx][my] = 1;
	if (check(mx + 2, my + 1)) s[mx + 2][my + 1] = 1;
	if (check(mx + 2, my - 1)) s[mx + 2][my - 1] = 1;
	if (check(mx + 1, my + 2)) s[mx + 1][my + 2] = 1;
	if (check(mx + 1, my - 2)) s[mx + 1][my - 2] = 1;
	if (check(mx - 2, my - 1)) s[mx - 2][my - 1] = 1;
	if (check(mx - 2, my + 1)) s[mx - 2][my + 1] = 1;
	if (check(mx - 1, my - 2)) s[mx - 1][my - 2] = 1;
	if (check(mx - 1, my + 2)) s[mx - 1][my + 2] = 1;
	
	for (int i = 1; i <= bx; i++) {
		for (int j = 1; j <= by; j++) {
			if (s[i][j]) f[i][j] = 0;//是控制点就置零
			else {
				if (i == 1 && j == 1) f[i][j] = 1;//否则的话是起点就置为1
				else f[i][j] = f[i - 1][j] + f[i][j - 1];//否则就递推
			}
		}
	}	
	std::cout << f[bx][by];
	return 0;
}

标签:过河,NOIP2002,int,bx,LL,P1002,check,my,mx
From: https://www.cnblogs.com/pangyou3s/p/18116331

相关文章

  • 洛谷p1002题解
    [NOIP2002普及组]过河卒题目描述棋盘上AAA点有一个过河卒,需要走到目标BB......
  • 洛谷p1002(过河卒)
    题目描述 如图,A点有一个过河卒,需要走到目标B点。卒行走规则:可以向下、或者向右。同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点。例如下图C点上的马可以控制9个点(图中的P1,P2…P8和C)。卒不能通过对方马的控......
  • P1002 [NOIP2002 普及组] 过河卒
    emmmm...据说是比较简单的dp?(再一次意识到自己的菜)链接:https://www.luogu.com.cn/problem/P1002题目:总的思路就是一个状态转移方程吧:dp[x][y]=dp[x-1][y]+dp[x][y-1];然后如果发现这个点不能通过,那么强制修改dp[x][y]=0;代码:#include<iostream>#include<vector>#inc......
  • 【洛谷P1036】 [NOIP2002 普及组] 选数
    一、题目:二、解题思路:本文章采用的解决方法是递归与DFS(深度优先搜索)。以下图是思路图:1.首先-确定位置题目说4个数字取三个数,所以考虑的只有三个位置和这三个位置分别放什么数值。从第一个位置开始放数。2.其次-开始放数分为4种可能,第一位置可以先放3,那么第二个位置......
  • 【华为OD机试真题】A卷-士兵过河(Python)
    一、题目描述【华为OD机试真题】A卷-士兵过河(Python)题目描述:一支N个士兵的军队正在趁夜色逃亡,途中遇到一条湍急的大河。敌军在T的时长后到达河面,没到过对岸的士兵都会被消灭。现在军队只找到了1只小船,这船最多能同时坐上2个士兵。1)当1个士兵划船过河,用时为a[i];0<=i<......
  • P1037 [NOIP2002 普及组] 产生数 python 题解
    原题链接:产生数原理解释本题就是基本的dfs,对每一个数遍历深搜,得到他能变化的所有情况,最后相乘就是结果,网上都是c的解法,需要用到高精度,但是python可以处理大数,不需要。vis[]判断该数是否变换过,防止重复以n=123,k=2,变换列表x=[1,3],y=[3,4],即1->3,3->4:先遍历1:遍历......
  • 每日一题 第三十五期 洛谷 过河卒
    [NOIP2002普及组]过河卒题目描述棋盘上AAA点有一个过河卒,需要走到目标BB......
  • P1036 [NOIP2002 普及组] 选数
    思路:也算典型的dfs,题目就是要求从n个数中选择k个数,计算这k个数的和,看这个和是否是素数。我们知道在dfs时相当于是进行全排列,而结果要求的是组合后和的情况。根据排列和组合的关系,他们之间差K!倍,所以需要在dfs求得个数cnt后除以k!。题目:AC代码:#include<algorithm>#include<io......
  • 青蛙过河(前缀+二分)
    1importjava.util.*;23publicclassMain{4publicstaticvoidmain(String[]args){5Scannerscanner=newScanner(System.in);6intn=scanner.nextInt();7longx=scanner.nextLong();8//前缀和9lo......
  • P1002 [NOIP2002 普及组] 过河卒(动态规划)
    #include<bits/stdc++.h>usingnamespacestd;longlongdp[30][30];boolm[30][30];intmain(){ intAx,Ay,Mx,My; cin>>Ax>>Ay>>Mx>>My; Ax+=2;Ay+=2;Mx+=2;My+=2; dp[2][1]=1; m[Mx][My]=1; m[Mx-2][My-1]......