zoj 3777(状态压缩dp)

来源:互联网 发布:怎么在淘宝上收藏店铺 编辑:程序博客网 时间:2024/04/27 21:45
// 题意:求一个长度为n的序列 所有的排列组成的疲劳值大于m的数量// 也就是求一个矩阵每行每列只能取一个得到的所有数字大于m共有多少种// n最大为12 m最大为500 所以采用状态压缩// 学习了别人的思路 dp[i][j] 表示状态为i,疲劳值大于等于j的排列有多少种// 接着就是由dp[i][j]推导出 dp[(1<<n) - 1][m] 即可#include <algorithm>#include <iostream>#include <string.h>#include <stdlib.h>#include <stdio.h>using namespace std;int sum[15];int dp[1<<13][505];int calcu(){    sum[1] = 1;    for(int i = 2; i <= 12; i++)        sum[i] = sum[i - 1] * i;    return 0;}int gcd(int a, int b){    return b == 0? a: gcd(b, a%b);}int main(){    int t;    int ss[15][15];    calcu();    cin>>t;    int cnt;    while(t--)    {        int n, m;        cin>>n>>m;        for(int i = 1; i <= n; i++)            for(int j = 1; j <= n; j++)                cin>>ss[i][j];        memset(dp, 0, sizeof dp);        dp[0][0] = 1;        for(int i = 0; i <= (1<<n); i++)        {            cnt = 0;            for(int j = 1; j <= n; j++)                if(i & (1 << (j - 1)))                    cnt ++;                        for(int j = 1; j <= n; j++)            {                if(i & (1<<(j - 1)))                    continue;                for(int k = 0; k <= m; k++)                    if(k + ss[cnt + 1][j] >= m)                        dp[i + (1<<(j - 1))][m] += dp[i][k];                    else                        dp[i + (1<<(j - 1))][k + ss[cnt + 1][j]] += dp[i][k];            }        }        if(dp[(1<<n) - 1][m] == 0)            cout<<"No solution"<<endl;        else {            int fn = gcd(dp[(1<<n) - 1][m], sum[n]);            cout<<sum[n]/fn<<'/'<<dp[(1<<n) - 1][m]/fn<<endl;        }    }        return 0;}

0 0