zoj 3777 Problem Arrangement

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5264

题意:给出n道题目以及每一道题目不同时间做的兴趣值,让你求出所有做题顺序中兴趣值大于等于m的比例。用一个分数表示。

状压dp。 枚举每一个状态,用二进制表示。dp[i][j]表示第i个题目,兴趣值为j的个数。

转移方程 dp[i|(1<<j)][k+a[num][j]]+=dp[i][k];兴趣值大于m的为 dp[1|(1<<j)][m]+=dp[i][k];

 1 #include <cstdio>

 2 #include <cstring>

 3 #include <algorithm>

 4 #define LL long long

 5 using namespace std;

 6 

 7 int t,n,m;

 8 int p[15][15];

 9 int dp[1<<13][1000];

10 int f[10000];

11 

12 LL gcd(LL a,LL b)

13 {

14     return b==0?a:gcd(b,a%b);

15 }

16 

17 int main()

18 {

19     scanf("%d",&t);

20     f[1]=1;

21     for(int i=2; i<=12; i++)

22     {

23         f[i]=f[i-1]*i;

24     }

25     while(t--)

26     {

27         scanf("%d%d",&n,&m);

28         memset(dp,0,sizeof(dp));

29         for(int i=0; i<n; i++)

30         {

31             for(int j=0; j<n; j++)

32             {

33                 scanf("%d",&p[i][j]);

34             }

35         }

36         dp[0][0]=1;

37         for(int i=0; i<=(1<<n); i++)

38         {

39             int num=0;

40             for(int j=0; j<n; j++)

41             {

42                 if(i&(1<<j)) num++;

43             }

44             for(int j=0; j<n; j++)

45             {

46                 if(i&(1<<j)) continue;

47                 for(int k=0; k<=m; k++)

48                 {

49                     if(k+p[num][j]>=m)

50                     {

51                         dp[i|(1<<j)][m]+=dp[i][k];

52                     }

53                     else

54                     {

55                         dp[i|(1<<j)][k+p[num][j]]+=dp[i][k];

56                     }

57                 }

58             }

59         }

60         if(dp[(1<<n)-1][m]==0)

61         {

62             printf("No solution\n");

63         }

64         else

65         {

66             int g=gcd(f[n],dp[(1<<n)-1][m]);

67             printf("%d/%d\n",f[n]/g,dp[(1<<n)-1][m]/g);

68         }

69     }

70     return 0;

71 }
View Code

 

你可能感兴趣的:(gem)