题目描述:小扣注意到秋日市集上有一个创作黑白方格画的摊位。摊主给每个顾客提供一个固定在墙上的白色画板,画板不能转动。画板上有 n * n 的网格。绘画规则为,小扣可以选择任意多行以及任意多列的格子涂成黑色,所选行数、列数均可为 0。
小扣希望最终的成品上需要有 k 个黑色格子,请返回小扣共有多少种涂色方案。
注意:两个方案中任意一个相同位置的格子颜色不同,就视为不同的方案
思路:
假设选择了a行b列,那么此时所图的格子个数sum=(a+b)n-ab,a*b是重复的格子数。选择a行的组合数就是C C n a \ C_n^a Cna,选择b列的组合数就是 C n b \ C_n^b Cnb,遍历sum=k的行列的组合数,结果就是行的组合数和列的组合数的乘积。
public class leetcode_22 {
public static void main(String[] args) {
}
/**
*
* @param n n*n的方格
* @param k 需要 图 K 个方格
* @return
*/
public int paintingPlan(int n, int k) {
int sum = 0;//I行J列可以图出的颜色个数
int ans = 0;//存储最终的结果
//全涂满了就只有一种方案
if(k==n*n){
return 1;
}
//i行j列
for (int i = 0; i < n; i++) {
for (int j = 0; j <n ; j++) {
sum = (i+j)*n-i*j;
if(sum==k){
int x = combain(n,i);//i行的组合数
int y = combain(n,j);//j行的组合数
ans+=x*y;
}
}
}
return ans;
}
/**
*n行或N列中取x行的组合数
* @param n
* @param m
* @return
*/
public static int combain(int n,int m){
int ans = 1;
for(int i=n; i>m; i--) {
ans *= i;
}
for(int i=n-m; i>0; i--) {
ans /= i;
}
return ans;
}
}