问题描述:
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));
}
}