放棋子

来源:互联网 发布:数控线切割3b编程例题 编辑:程序博客网 时间:2024/06/10 05:59

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;}
0 0