codevs P1010 过河卒

古老而悠久的问题

上一次提这个问题——我还是个渣。
教练说这是用递推法。。。。。。当然了我就丢个递推过去(当然是瞎递推的 ),当时连个样例都过不了,我不知道我是怎么想的居然还敢提交!
而且连结果也没有,都是一把的RE。
后来拿去问教练,这 * * 也不理我

只好拿这个题目去问信息老师,然而我们学校在前几届高考信息技术高考凭着省内各路牛校压根不鸟信息技术这个东西所以水了个技术名校,(求喜高人请忽略)老师差不多会操作visual basic然而C++。。。。。。还好吧,对付我这种渣还是有两下的。

而且我碰到的都是好人啊,非常非常非常非常非常非常感谢千千老师帮我解答了这个问题。(然而我这个 * * * * * *的东西居然把他的源代码弄丢了),所以这个过河卒就这么不了了之。

好吧,没办法今天在codevs黄金天梯赛又碰到了这个冤家,追忆往昔还是有点scare。
然而我把它AC了**[手动滑稽]**

过河卒

题目描述 Description
如图,A 点有一个过河卒,需要走到目标 B 点。卒行走规则:可以向下、或者向右。同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点。例如上图 C 点上的马可以控制 9 个点(图中的P1,P2 … P8 和 C)。卒不能通过对方马的控制点。

棋盘用坐标表示,A 点(0,0)、B 点(n,m)(n,m 为不超过 20 的整数,并由键盘输入),同样马的位置坐标是需要给出的(约定: C不等于A,同时C不等于B)。现在要求你计算出卒从 A 点能够到达 B 点的路径的条数。

1<=n,m<=15
在这里插入图片描述

输入描述 Input Description
键盘输入
   B点的坐标(n,m)以及对方马的坐标(X,Y){不用判错}

输出描述 Output Description
屏幕输出
    一个整数(路径的条数)。

数据范围及提示 Data Size & Hint
如描述

样例输入 Sample Input样例输出 Sample Output
6 6 3 217

题解

说真的基本都是注释,调试的时候代码加来删去弄成这样。
但这些注释都很有价值的。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxm=2019;
int e[maxm][maxm],a,b,m,n; 
bool vis[maxm][maxm];

bool on(int x,int y){
	if(x<0||y<0||x>n||y>m) return 0;
//	else if(x==a-2&&y=b-1) return 0;
//	else if(x==a-1&&y=b-2) return 0;
//	else if(x==a+2&&y=b-1) return 0;
//	else if(x==a+1&&y=b-2) return 0;
//	else if(x==a-2&&y=b+1) return 0;
//	else if(x==a-1&&y=b+2) return 0;
//	else if(x==a+2&&y=b+1) return 0;
//	else if(x==a+1&&y=b+2) return 0;
	return 1;
}

int que[3][maxm],head=1,tail=2;
void bfs(int x,int y){ 
	que[1][head]=x;
	que[2][head]=y;
	
	while(tail-head){
		for(int i=1;i<=2;i++){
			int tx=que[1][head],ty=que[2][head];
			if(i==1){ty++;}
			else{tx++;}
			
			if(on(tx,ty)&&vis[tx][ty]==0){
				que[1][tail]=tx;
				que[2][tail++]=ty;
				if(on(tx-1,ty)) e[tx][ty]+=e[tx-1][ty];
				if(on(tx,ty-1)) e[tx][ty]+=e[tx][ty-1];
				vis[tx][ty]=1;
				if(tx==n&&ty==m) return;
			}
		}
		head++;
	}
	return;
}

void init(){
	e[0][0]=1;
	vis[a][b]=1;
	vis[a-2][b-1]=vis[a-1][b-2]=1;  //记录马的点和马可跳的点
	vis[a+2][b-1]=vis[a+1][b-2]=1;
	vis[a-2][b+1]=vis[a-1][b+2]=1;
	vis[a+2][b+1]=vis[a+1][b+2]=1;
	return;
}

int main(){
//	freopen("gin.txt","r",stdin);
	std::ios::sync_with_stdio(false);
	cin>>n>>m>>a>>b;
	init();
	bfs(0,0);
//	for(int i=0;i<=6;i++){
//		for(int j=0;j<=6;j++){
//			cout<<e[i][j]<<"      ";
//		}cout<<endl;
//	}
	cout<<e[n][m]<<endl;
	return 0;
}

我写这道题的时候直接BFS了。
其实这道题BFS和递推有个什么区别。。。。。。

解题流程大概酱紫:
1.首先把马的位置和所有马可以跳到的位置的vis 都设置为1,这样可以防止进入这些点。
2.二维数组e用于统计走到该点使用的方案数
3.从起点开始BFS,把所有搜到的点做这样的处理(边搜边处理):每个点的方案数等于左边点的方案数加上边点的方案数。如果左边点或者上边点是马或者马可以跳到的位置亦或是数组越界,那就令当前点加上0,就当做已经统计了这个左边点或者上边点是马或者马可以跳到的位置亦或是数组越界的点了。
4.最后直接输出e[n][m] 问题自然解决。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值