过河卒(洛谷p1002)

题目链接:P1002 [NOIP2002 普及组] 过河卒 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

会下象棋的大家都知道,过河卒是能左右移动的,而这道题说的是只能向右移动,这是一个区别,也简化了题目,像这道题用到的方法还是递推,和昨天那道题一样,即a[i][j] = a[i - 1][j] + a[i][j - 1]对吧,一个点的方法数就等于他左边那个点的方法数加上上边那个点的方法数,然后同理,就可以一直递推下去,假设没有马的存在,当目标坐标为(3,3)时,就可以得到如下图

因为两条边上的方法数很简单恒为1,只有1条路能到达

然后如果在复杂了也是同理,,,但现在的问题是多了一只🐎,那怎么办呢,有马的地方就是到不了的地方,将马和马控制的地方定为0?没错这样就可以了,但这里有个魔鬼细节,否则你最后提交有两个地方过不了,那就是当马控制的地方出现在特殊的两条边上,那么他后面的点就不是1了,而是0,这个不难理解吧,因为唯一的一条路被挡了,后面都到不了了

贴代码

#include<iostream>
using namespace std;
int main() {
	long long a[22][22] = { 0 };
	
	int bx, by, hx, hy;
	cin >> bx >> by >> hx >> hy;
//	for(int i=0;i<)
	bx += 1, by += 1, hx += 1, hy += 1;
	for (int i = 1; i <= 21; i++) {
		if ((hx != 1 || hy != i) && (hx + 2 != 1 || hy - 1 != i) && (hx + 2 != 1 || hy + 1 != i) &&
			(hx + 1 != 1 || hy + 2 != i) && (hx + 1 != 1 || hy - 2 != i) && (hx - 1 != 1 || hy - 2 != i) && (hx - 1 != 1 || hy + 2 != i)
			&& (hx - 2 != 1 || hy - 1 != i) && (hx - 2 != 1 || hy + 1 != i))
			a[1][i] = 1;
		else
			break;
	
	}
	for (int i = 1; i <= 21; i++) {

		if ((hx != i || hy != 1) && (hx + 2 != i || hy - 1 != 1) && (hx + 2 != i || hy + 1 != 1) &&
			(hx + 1 != i || hy + 2 != 1) && (hx + 1 != i || hy - 2 != 1) && (hx - 1 != i || hy - 2 != 1) && (hx - 1 != i || hy + 2 != 1)
			&& (hx - 2 != i || hy - 1 != 1) && (hx - 2 != i || hy + 1 != 1))
			a[i][1] = 1;
		else
			break;
	}
	for (int i = 2; i <= bx; i++) {
		for (int j = 2; j <= by; j++) {
			if ((i != hx || j != hy) && (i != hx - 2 || j != hy - 1) && (i != hx - 2 || j != hy + 1) && (i != hx - 1 || j != hy - 2)
				&& (i != hx - 1 || j != hy + 2) && (i != hx + 1 || j != hy + 2) && (i != hx + 1 || j != hy - 2) &&
				(i != hx + 2 || j != hy - 1) && (i != hx + 2 || j != hy + 1))
				a[i][j] = a[i - 1][j] + a[i][j - 1];
			
		}
	}
	cout << a[bx][by]<<"\n";
	for (int i = 0; i < 22; i++) {
		for (int j = 0; j < 22; j++)
			cout << a[i][j] << "  ";
		cout << "\n";
	}
	return 0;
}

别看if里面一大堆,实际上就是避开马的控制位置,而break的作用就是上面的那个魔鬼细节的体现.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值