首页 > 其他分享 >[OI] 洛谷P1001过河卒题解

[OI] 洛谷P1001过河卒题解

时间:2024-01-19 23:22:34浏览次数:34  
标签:25 洛谷 OI int 题解 ++ 坐标 dy dp

[NOIP2002 普及组] 过河卒

题目描述

棋盘上 \(A\) 点有一个过河卒,需要走到目标 \(B\) 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 \(C\) 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。

棋盘用坐标表示,\(A\) 点 \((0, 0)\)、\(B\) 点 \((n, m)\),同样马的位置坐标是需要给出的。



现在要求你计算出卒从 \(A\) 点能够到达 \(B\) 点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。

输入格式

一行四个正整数,分别表示 \(B\) 点坐标和马的坐标。

输出格式

一个整数,表示所有的路径条数。

样例 #1

样例输入 #1

6 6 3 3

样例输出 #1

6

提示

对于 \(100 \%\) 的数据,\(1 \le n, m \le 20\),\(0 \le\) 马的坐标 \(\le 20\)。

【题目来源】

NOIP 2002 普及组第四题

题目分析

\(upd:\)迁移至博客园地址

马走日,象走田,卒子一去不复返

对于本题,卒子一开始的坐标为\((0, 0)\)

而对于卒子,所有格子的状态无非2种: 能走与不能走(1或者0)

但是我们还需要令起点从(0, 0)到(1, 1),即向右下方偏移一位

设dp[i][j]为从1到i的路径条数,我们可以得到对状态进行转移的方程:

\(dp[i][j] = dp[i - 1][j] + dp[i][j - 1]\)

long long dp[25][25];//别忘了定义

但是我们需要先给定格子状态再偏移

所以我们可以bitset一个mp[25][25]用来存储每个格子的状态

(开大些没坏处)

bitset<25> mp[N];

那么什么格子不能走呢?

马能走的格子啊(废话)

所以dp[马的x - 1][马的y + 2] = 0

dp[马的x - 1][马的y - 2] = 0

dp[马的x - 1][马的y + 2] = 0

dp[马的x + 1][马的y - 2] = 0

dp[马的x + 1][马的y + 2] = 0

dp[马的x - 2][马的y + 1] = 0

dp[马的x - 2][马的y + 1] = 0

dp[马的x + 2][马的y + 1] = 0

dp[马的x + 2][马的y + 1] = 0

如果觉得这些代码过于冗杂,可以两个数组 dx[8], dy[8]

代码如下:

int dx[8] = {1, 1, -1, -1, 2, 2, -2, -2};
int dy[8] = {2, -2, 2, -2, 1, -1, 1, -1};
//数组的元素必须一一对应

然后使用for循环处理mp

代码:

for(int i = 0; i < 8; i++)
{

    int nx = x + dx[i], ny = y + dy[i];//x为马的坐标x,y为马的坐标y`

    if(1 <= nx && nx <= n && 1 <= ny && ny <= m)
    {
        mp[nx][ny] = ture;//mp为一个二进制数组,相当于bool数组,其中的值表示能不能走
    }
}

接下来就是偏移了

这个时候:这个\(dp[i][j] = dp[i - 1][j] + dp[i][j - 1]\)就派上用场了

dp[1][1] = 1;//别忘了将第一个格子初始化
for(int i = 1; i <= n; i++)
{
    for(int j = 1; j <= m; j++)
    {
        if(i == 1 && j == 1) coutinue;
        dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
        if(mp[i][j])dp[i][j] = 0;//如果走到马的控制点路径为0
    }
}

最后输出dp[n][m]

cout << dp[n][m] << '\n';

完整AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    long long dp[25][25] = {0};
    bitset<25> mp[25];
    int dx[8] = {1, 1, -1, -1, 2, 2, -2, -2};
    int dy[8] = {2, -2, 2, -2, 1, -1, 1, -1};
    signed main()
    {
    	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    	int n, m, x, y;cin >> n >> m >> x >> y;
    	n++, m++, x++, y++;
    	
    	mp[x][y] = true;
    	for(int i = 0; i < 8; i++)
    	{
    		int nx = x + dx[i], ny = y + dy[i];
    		if(1 <= nx && nx <= n && 1 <= ny && ny <= m)mp[nx][ny] = true;
    	}
    	dp[1][1] = 1;
    	for(int i = 1; i <= n; i++)
    	{
    		for(int j = 1; j <= m; j++)
    		{
    			if(i == 1 && j == 1) continue;
    			dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
    			if(mp[i][j])dp[i][j] = 0;
    		}
    	}
    	cout << dp[n][m] << endl;
    	
    	return 0;
    }

标签:25,洛谷,OI,int,题解,++,坐标,dy,dp
From: https://www.cnblogs.com/zhaoyihang/p/17975834

相关文章

  • [BZOJ3786] 星系探索 题解
    题目链接:\(BZOJ\)本题通过\(dyf\_DYF\)的题解理解\(ETT\),代码则借鉴\(lcyfrog\)的题解,图片则使用了何太郎的题解。在此笔者感谢这三位神犇。声明变量:\(ls\):左儿子\(rs\):右儿子\(sz\):子树大小\(rk\):对应堆值\(fa\):节点父亲\(sm\):子树权值和\(p\):\(1/-1\)表示第一......
  • P4345 [SHOI2015] 超能粒子炮·改 题解
    P4345[SHOI2015]超能粒子炮·改题解求\[\sum_{i=0}^k\binom{n}{i}\pmod{2333}\]思路这种模数小的组合数计数问题可以考虑Lucas定理,试试呗。如果按余数分类不好优化,可以按商分类求和,这样一来套个前缀和可以得到一个递推式,注意最后一块商可能是不整的,单独拿出来即可。......
  • Essay - OI tricks
    ......
  • GD动角题解(2024.1.19)
    $upd:$2024.1.19改正了一些错误题目讲解只看第三题若在三角板开始转动的同时,射线\(OC\)也绕点\(O\)以每秒25°的速度逆时针旋转一周,从旋转开始多长时间,射线\(OC\)平分\(∠BOD\)?最重要的一点:动角角度\(=\)初始值\(+\)角度\((vt)\)明确了这一点之后我们看题这题可以分......
  • 题解:阶乘
    题目大意给定一个数\(n\),求两个数\(a\),\(b\),使\(\Large\frac{a!}{b!}\normalsize=n(a>b)\)。若有无数组解输出-1。多组数据。思路简析\[a!=a\times(a-1)\times(a-2)\times\cdots\times2\times1\]\[b!=b\times(b-1)\times(b-2)\times\cdots\times2\times1\]......
  • 【LGR-172-Div.4】洛谷入门赛 #19 题解
    比赛链接:\(link\)T1分饼干I题目描述洛谷网校举行了期末考试,同学们经过课程的学习,考出了优异的成绩。Z在考试中获得了第一名,yz在考试中获得了第二名,老师决定买一些饼干奖励两名小朋友。老师买了三盒饼干,第一盒有\(a\)块饼干,第二盒有\(b\)块饼干,第三盒有\(c\)块饼干......
  • 题解 CF1909H
    题意给定一个长度为\(n\)的排列\(p\)。你可以进行不超过\(10^6\)次操作,每次操作是选择一个长度为偶数的区间\([l,r]\),然后交换\((p_l,p_{l+1}),(p_{l+2},p_{l+3}),...,(p_{r-1},p_r)\)。你需要将排列排序。数据范围:\(n\le3\times10^5\)。题解刚才有个群友问我Z......
  • $20240119$ 练习题解
    \(20240119\)练习题解CF472D通过尝试我们容易发现,与点\(1\)最近的点一定是直接儿子。我们要是把它作为突破点,那就成功了一半了。假设点\(2\)与点\(1\)最近,又假设我们可以用函数\(F(x)\)来确定\(x\)点的子树形态。那我们会发现如果我们还有剩余的节点,那么剩余的节点......
  • 洛谷 P9869 [NOIP2023] 三值逻辑 题解
    Solution模拟程序,容易发现每个点最后的取值都是定值或一个点的初始值(可能是该值取反)。最后是定值的点可以确定初始值,最后取值由该点决定的点也可以确定取值。求出这些取值,答案加上取之为U的点的个数。即第\(i\)个点最后的取值是\(to_i\)的初始值,\(sg_i\)表示是否取反,那......
  • 洛谷 P9751 [CSP-J 2023] 旅游巴士 题解
    Solution能在起点等\(k\)的非负整数倍相当于能在任意点等\(k\)的非负整数倍。由于离开的时间要是\(k\)的负整数倍,将每个点拆成\(k\)个点,\(dis_{i,j}\)表示到了第\(i\)个点长度\(\bmod\text{}k\equivj\)的最短路径。转移时若时间未到,直接在原地等\(k\)的负整......