比赛安排题目。将i题放在第j个的有趣程度为Pij。求有趣程度和超过m的方案数。
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5264
dp[i][j],i表示当前的状态,j表示当前状态的有趣程度和,dp[i][j]存的是方案数。
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define pb push_back
const int inf = 0x3f3f3f3f;
const int mod = 1000000007;
const int maxn = 10000 + 10;
int dp[1 << 12][555], t, n, m, p[12][12];
int gcd(int a, int b){
return b == 0 ? a : gcd(b, a % b);
}
int Fact(int x){
int ret = 1;
for(int i=1; i<=x; i++)
ret *= i;
return ret;
}
int main(){
scanf("%d", &t);
while(t--){
scanf("%d%d", &n, &m);
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
scanf("%d", &p[i][j]);
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
int tot = (1 << n) - 1;
for(int i=0; i<=tot; i++){
for(int j=0; j<=m; j++)
if(dp[i][j]){
int cnt = 0;
for(int k=0; k<n; k++) if(i & (1 << k)) cnt++;
for(int k=0; k<n; k++)
if(!(i & (1 << k))){
dp[i | (1 << k)][min(m, j + p[k][cnt])] += dp[i][j];//注意有趣程度和超过m的,按m计算
}
}
}
int a = dp[tot][m];
if(!a){
puts("No solution");
continue;
}
int b = Fact(n);
int c = gcd(a, b);
printf("%d/%d\n", b / c, a / c);
}
return 0;
}