// 題意:求一個長度爲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;
}
zoj 3777(狀態壓縮dp)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.