zoukankan      html  css  js  c++  java
  • ZOJ 3777 Problem Arrangement

    https://cn.vjudge.net/problem/ZOJ-3777

    题目

    某人出题,有N道,觉得题目难度按题目顺序增加很没意思。他发现将编号为$i$的题目放到$j$号位置能增加$P_{ij}$的趣味值,于是他将题目随机打乱,计算趣味值,如果达不到他想要的趣味值M就将题目重新随机打乱,如此循环。求他打乱次数的期望。

    输入N (1 <= N <= 12)、M (1 <= M <= 500).和矩阵Pij (0 <= Pij <= 100),输出一个不可约分的分数。如果永远都达不到,输出“No solution”。

    Sample Input

    2
    3 10
    2 4 1
    3 2 2
    4 5 3
    2 6
    1 3
    2 4
    

    Sample Output

    3/1
    No solution
    

    题解

    如果知道概率,那么$1/$概率就能得到期望

    因此就是

    [frac{1}{frac{符合条件的情况}{总情况}}]

    总情况是$N!$,可以直接计算,符合条件的情况可以用DP

    N<=12,所以可以用状态压缩dp,设$dp[k][F]$为选了k表示的题目,趣味值为F的种类个数,于是可以得到

    [dp[0][0]=1]

    [dp[k][F]=sum{dp[koplus x][F-P_?]}]

    其中$P_?$是当前问题在这个位置能加的趣味值

    由于要计算大于等于M的种类数,于是改变一下,将大于M的都设为M

    [dp[k|x][F+P_?]+=dp[k][F]]

    这样设的原因是 $k|x>k>k oplus x$,$oplus$表示异或

    AC代码

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define REP(r,x,y) for(register int r=(x); r<(y); r++)
    #define REPE(r,x,y) for(register int r=(x); r<=(y); r++)
    #define PERE(r,x,y) for(register int r=(x); r>=(y); r--)
    #ifdef sahdsg
    #define DBG(...) printf(__VA_ARGS__), fflush(stdout)
    #else
    #define DBG(...) (void)0
    #endif // sahdsg
    using namespace std;
    typedef long long LL;
    
    #define MAXN 30000007
    int n,m;
    int p[12][12];
    int dp[1<<12][507];
    inline int cnt(int i) {
    	i = (i&0x55555555)+((i>>1)&0x55555555);
    	i = (i&0x33333333)+((i>>2)&0x33333333);
    	i = (i&0x0f0f0f0f)+((i>>4)&0x0f0f0f0f);
    	i = (i&0x00ff00ff)+((i>>8)&0x00ff00ff);
    	i = (i&0x0000ffff)+((i>>16)&0x0000ffff);
    	return i;
    }
    int f[13];
    inline int gcd(int a, int b) {
    	return b==0? a: gcd(b, a%b);
    }
    int main() {
    	f[0]=1;
    	REPE(i,1,12) f[i]=f[i-1]*i;
    	int t; scanf("%d", &t);
    	while(0<t--) {
    		scanf("%d%d", &n, &m);
    
    		REP(i,0,n) {
    			REP(j,0,n) {
    				scanf("%d", &p[i][j]);
    			}
    		}
    
    		memset(dp,0,sizeof dp);
    		dp[0][0]=1;
    		REP(i,0,(1<<n)-1) {
    			int ones=cnt(i);
    			REPE(j,0,m) if(dp[i][j]) {
    				REP(x,0,n) if(!(i&(1<<x))){
    					int k=j+p[x][ones]; if(k>m) k=m;
    					dp[i|(1<<x)][k]+=dp[i][j];
    				}
    			}
    		}
    		int ans=dp[(1<<n)-1][m];
    		if(!ans) puts("No solution");
    		else {
    			int ans2=f[n];
    			int g=gcd(ans,ans2);
    			printf("%d/%d
    ", ans2/g, ans/g);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Vulkan
    C# Optimization
    C# Bridge Pattern(Handle/Body)
    Favorite Games
    Unity Particle System Sorting Order
    UGUI
    C# Language Specification
    接口的显式实现和隐式实现
    C#反射机制
    wcf 使用sqlMembership证书认证
  • 原文地址:https://www.cnblogs.com/sahdsg/p/10927053.html
Copyright © 2011-2022 走看看