1. 程式人生 > >洛谷 P1002 過河卒(一維dp)

洛谷 P1002 過河卒(一維dp)

題目描述

棋盤上 AA 點有一個過河卒,需要走到目標 BB 點。卒行走的規則:可以向下、或者向右。同時在棋盤上 CC 點有一個對方的馬,該馬所在的點和所有跳躍一步可達的點稱為對方馬的控制點。因此稱之為“馬攔過河卒”。

棋盤用座標表示, AA 點 (0, 0)(0,0) 、 BB 點 (n, m)(n,m) ( nn , mm 為不超過 2020 的整數),同樣馬的位置座標是需要給出的。

現在要求你計算出卒從 AA 點能夠到達 BB 點的路徑的條數,假設馬的位置是固定不動的,並不是卒走一步馬走一步。

輸入輸出格式

輸入格式:

 

一行四個資料,分別表示 BB 點座標和馬的座標。

 

輸出格式:

 

一個數據,表示所有的路徑條數。

 

輸入輸出樣例

輸入樣例#1: 複製

6 6 3 3

輸出樣例#1: 複製

6

說明

結果可能很大!

剛開始用dfs做的,直接TLE,看了題解才發現是線性dp,因為當前狀態只取決於dp[i-1][j]和dp[i][j-1],兩者相加就行,然後就是馬的位置控制,我沒下過象棋不知道橫的“日”也可以,卡了許久,百度了才知道,著實是很慚愧

#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
long long dp[25][25],map[25][25];
void mark(int x,int y)
{
	map[x][y]=1;
	map[x+1][y+2]=1;
	map[x-1][y-2]=1;
	map[x+1][y-2]=1;
	map[x-1][y+2]=1;
	map[x+2][y+1]=1;
	map[x-2][y-1]=1;
	map[x-2][y+1]=1;
	map[x+2][y-1]=1;
}
int main()
{
	int n,m,hx,hy,i,j,k;
	while(cin>>n>>m>>hx>>hy)
	{
		memset(map,0,sizeof(map));
		mark(hx,hy);//標記馬的控制位置 
		dp[0][0]=1;
		for(i=0;i<=n;i++)
		{
			for(j=0;j<=m;j++)
			{
				if(j==0 && i!=0)//防止越界 
				{
					dp[i][j]=dp[i-1][j];
				}
				else if(i==0 && j!=0)
				{
					dp[i][j]=dp[i][j-1];
				}
				else if(i==0 && j==0);
				else 
				{
					dp[i][j]=dp[i-1][j]+dp[i][j-1];
				}
				if(map[i][j]) dp[i][j]=0;//如果是馬控制點,直接清空這個點 
			}
		}
		cout<<dp[n][m]<<endl;
	}
	return 0;
}