您的位置:首页 > 其它

zoj 3777(状态压缩dp)

2016-04-05 17:59 267 查看
// 题意:求一个长度为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
);
cout<<sum
/fn<<'/'<<dp[(1<<n) - 1][m]/fn<<endl;
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  动态规划