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; }
相关文章推荐
- C++动态规划之最长公子序列实例
- C++动态规划之背包问题解决方法
- C#使用动态规划解决0-1背包问题实例分析
- 动态规划
- C++ 动态规划
- DP(动态规划) 解游轮费用问题
- 动态规划的用法——01背包问题
- 动态规划的用法——01背包问题
- 《收集苹果》 动态规划入门
- 《DNA比对》蓝桥杯复赛试题
- 《背包问题》 动态规划
- 自顶向下动态规划解决最长公共子序列(LCS)问题
- 初学ACM - 半数集(Half Set)问题 NOJ 1010 / FOJ 1207
- 关于爬楼梯的动态规划算法
- 动态规划 --- hdu 1003 **
- DP问题各种模型的状态转移方程
- 0-1背包解题过程
- 背包问题
- USACO 3.2.2:Stringsobits
- 字符串编辑距离