http://www.wikioi.com/problem/1010/
分析:
最先想到的是回溯,在Wikioi_1010 是680ms過的,但是在另外一個shuoj上就是TLE 然後就想起DP(2ms過)了;
dp[i] [j] 存的是到達 (i,j)位置的方法數,初始化爲1,對於馬控制點應該是走不到的,所以設爲0;
至於狀態轉移,由於卒只能向下和向右走,所以一般的: dp [ i ] [ j ] = dp[ i-1] [ j ] + dp [ i ] [ j-1 ] ;
注意i=0 和 j=0 的情況:
i=0 : dp[ i ][ j ] = dp[ i ] [ j-1 ];
j=0 : dp[ i ][ j ] = dp[ i-1 ] [ j ];
代碼:
#include <stdio.h> int ans; int n,m,cx,cy; int abs(int e) { return e > 0 ? e:-e; } bool judge(int x,int y) { if(x==cx && y==cy) return 0; if(abs(x-cx)==1 && abs(y-cy)==2 || abs(x-cx)==2 && abs(y-cy)==1) return 0; return 1; } void dfs(int x,int y) { if(x==n && y==m){ ans++; return; } if(x>n || y>m) return; if(judge(x,y)==0) return; dfs(x+1,y); dfs(x,y+1); return; //return dfs(a+1,b)+dfs(a,b+1); } int main() { while(scanf("%d%d%d%d",&n,&m,&cx,&cy)!=EOF) { if(judge(n,m)==0) ans=0; else dfs(0,0); printf("%d\n",ans); } }
#include <iostream>
#include <stdio.h>
using namespace std;
#define MAXN 24
int n,m,cx,cy;
long long dp[MAXN][MAXN];
void mark(int x,int y)
{
dp[x][y] = 0;
dp[x+2][y+1] = 0;
dp[x+1][y+2] = 0;
if(x>=1)dp[x-1][y+2] = 0;
if(x>=2)dp[x-2][y+1] = 0;
if(x>=2&&y>=1)dp[x-2][y-1] = 0;
if(x>=1&&y>=2)dp[x-1][y-2] = 0;
if(y>=2)dp[x+1][y-2] = 0;
if(y>=1)dp[x+2][y-1] = 0;
}
void init()
{
scanf("%d%d%d%d",&n,&m,&cx,&cy);
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
dp[i][j]=1;
mark(cx,cy);
}
int main()
{
init();
for(int i=0; i<=n; i++){
for(int j=0; j<=m; j++){
if((!dp[i][j])) continue;
if(i==0 && j==0) continue;
else if(i==0) dp[i][j] = dp[i][j-1];
else if(j==0) dp[i][j] = dp[i-1][j];
else dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
printf("%lld\n",dp[n][m]);
}