PKU 2704-Pascal's Travels

問題概要

NxNの非負整数が入ったマスがある.
(x,y)から移動出来る場所は(x,y)での値をdとすると,(x+d,y)か(x,y+d)とする.
(0,0)から(N-1,N-1)に移動する経路数を求めよ.

解法

(0,0)に近い所から順に動的計画法で計算する.

実装(C++)

#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long int lli;
struct State{
	int x,y,d;
	State(int x,int y):x(x),y(y){
		d=x+y;
	}
};
const bool operator<(const State &a,const State &b){
	return a.d>b.d;
}
int n;
int dx[2]={1,0},dy[2]={0,1};
inline bool valid(int x,int y){return x>=0&&x<n&&y>=0&&y<n;}
vector<string> MAP;
lli ac[35][35];
lli solve(){
	memset(ac,0,sizeof(ac));
	ac[0][0]=1;
	priority_queue<State> que;
	que.push(State(0,0));
	while(!que.empty()){
		State now(que.top());que.pop();
		int dist=MAP[now.x][now.y]-'0';
		if(dist==0)continue;
		for(int i=0;i<2;i++){
			int nx=now.x+dx[i]*dist,ny=now.y+dy[i]*dist;
			if(valid(nx,ny)){
				if(ac[nx][ny]==0){
					que.push(State(nx,ny));
				}
				ac[nx][ny]+=ac[now.x][now.y];
			}
		}
	}
	return ac[n-1][n-1];
}
int main() {
	for(;cin>>n;){
		if(n==-1)break;
		MAP=vector<string>(n);
		for(int i=0;i<n;i++){
			cin>>MAP[i];
		}
		cout<<solve()<<endl;
	}
	return 0;
}