Codeforces Round #14 E.Camels

問題概要

(x1,y1),(x2,y2),...,(xn,yn)を順に結んだ折れ線がある。
x1=1,x2=2,...,xn=nであり、1≦yi≦4で、各座標は全て整数である。
またすべての折れ線の部分はx軸に平行にはならない。


n,tが与えられるとき、このような折れ線のうち、

  • 山(yj-1 < yj > yj+1) がt個
  • 谷(yj-1 > yj < yj+1) がt-1個

あるものは何通りあるかを求めよ。


n≦20,t≦10である。

解法

折れ線を全てシミュレートする(3^n)のはおそらくTLE.
場合の数の問題の定石通りに動的計画法を用いる。


最新の2つのy座標および、山、谷の数をメモする動的計画法ならば数十msで解ける。
以下のコードでは、
dp[x座標+1][山の数][谷の数][一つ前のy座標][y座標]にその段階までの場合の数を記憶している。

ソースコード

int dp[20][11][10][4][4];

void run()
{
	int n,t; cin>>n>>t;
	rep(i,n)rep(u,11)rep(d,10)rep(j,4)rep(k,4)dp[i][u][d][j][k]=0;
	rep(i,4)rep(j,4)if(i!=j)dp[1][0][0][i][j]=1;
	
	for(int i=2;i<n;i++)
	rep(j,4)rep(k,4)rep(l,4)if(k!=l)
	rep(u,i/2+2)rep(d,i/2+2)
	{
		
		dp[i][u+(j<k&&k>l)][d+(j>k&&k<l)][k][l]+=
		dp[i-1][u][d][j][k];
	}
	
	int ans=0;
	rep(j,4)rep(k,4)ans+=dp[n-1][t][t-1][j][k];
	cout<<ans<<endl;
}