http://acm.zzu.edu.cn:8000/problem.php?cid=33&pid=0
Description
给你一个N*N的矩阵,每行有一个障碍(用1表示),数据保证任意两个障碍不在同一行,任意两个障碍不在同一列,要求你在这个矩阵上放N枚棋子(障碍的位置不能放棋子),要求你放N个棋子也满足每行只有一枚棋子,每列只有一枚棋子的限制,求有多少种方案。
Input
第一行一个N,接下来一个N*N的矩阵。N<=200
Output
一个整数,即合法的方案数。
Sample Input
2
0 1
1 0
Sample Output
1
HINT
错排问题,不懂可以先看这里,递推公式 dp[i] = (i-1) * (dp[i-1]+dp[i-2])
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
const int maxn = 105;
int dp[205][maxn];
void Init(){
memset(dp, 0, sizeof(dp));
dp[0][0] = dp[1][0] = 0;
dp[2][0] = 1;
for(int i = 3; i <= 200; i++){
int c = 0;
for(int j = 0; j <= 100; j++) {
dp[i][j] += dp[i-1][j]+dp[i-2][j]+c;
c = 0;
if(dp[i][j] >= 10000) {
c = dp[i][j]/10000;
dp[i][j] = dp[i][j]%10000;
}
}
for(int j = 0; j <= 100; j++) {
dp[i][j] = dp[i][j]*(i-1) + c;
c = 0;
if(dp[i][j] >= 10000) {
c = dp[i][j]/10000;
dp[i][j] = dp[i][j]%10000;
}
}
}
}
int main(){
int n;
Init();
while(scanf("%d", &n) == 1){
int a;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
scanf("%d", &a);
if(n == 1) printf("0\n");
else {
int i = 100;
while(!dp[n][i]) i--;
printf("%d", dp[n][i]);
for(i--; i >= 0; i--)
printf("%04d", dp[n][i]);
printf("\n");
}
}
return 0;
}