問題描述:
public class RedGreenTower {
/**
* 動態規劃解法,空間複雜度O(h*n)
* @param n 紅色方塊的個數
* @param m 綠色方塊的個數
* @return
*/
public static int solve(int n, int m) { //紅綠的總個數
/*
* 計算最大的h
* 由 h(h+1)/2 <= n+m 可得 h <= sqrt(2*(n+m)), 若h*(h+1) > 2*(n+m) h--;
*/
int h = (int) Math.sqrt(2*(n+m));
if(h*(h+1) > 2*(n+m))
h--;
//記錄每層總數的數組
int[] sumi = new int[h+1];
int sum = 0;
for(int k=1; k<=h; k++){
sum += k;
sumi[k] = sum;
}
/*
* 第i層剩餘j個紅色方塊的擺法總類爲
*/
int[][] dp = new int[h+1][n+1];
//初始化
if(m > 0){
dp[1][n] = 1;
}
dp[1][n-1] = 1;
/*
* 如果i+1層不放置紅色方塊:if(green >= i+1) dp[i+1][j]=dp[i+1][j]+dp[i][j]
* 如果i+1層放置紅色方塊: if(red >= i+1) dp[i+1][j-i-1] = dp[i+1][j-i-1]+dp[i][j]
*/
for(int i=1; i<h; i++) { //層數
for(int j=n; j>=0; j--) { //紅色剩餘的個數
int green = m - (sumi[i]-(n-j));
if(green >= i+1)
dp[i+1][j] = dp[i+1][j]+dp[i][j];
if(j >= i+1)
dp[i+1][j-i-1] = dp[i+1][j-i-1]+dp[i][j];
}
}
int ans = 0;
for(int k=0; k<=n; k++) {
ans += dp[h][k];
}
return ans;
}
public static void main(String[] args) {
System.out.println(solve(2,5));
}
}