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

    Zoj 3777 Problem Arrangement

    想法

    求多少种排列的收益大等于 (m) 可以用状压dp。
    (mask) 表示前 (i) 个数确定在哪几个位置。
    (f(mask, j)) 表示前 (i) 个数位置确定,收益大等于 (j) 的方案数。

    PS:比赛时想到折半,就上去写了,虽然发挥很稳定,但是还是写了好一会儿。还是状压好写,可惜没想出来。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define rep(i,a,b) for(int i=(a);i<(b);++i)
    #define per(i,a,b) for(int i=(b)-1;i>=(a);--i)
    #define sz(a) (int)a.size()
    #define de(a) cout<<#a<<" = "<<a<<endl
    #define dd(a) cout<<#a<<" = "<<a<<" "
    typedef long long ll;
    typedef pair<int,int> pii;
    typedef vector<int> vi;
    
    const int N=1<<12, M=505;
    
    int n,m;
    int a[22][22], f[N][M], cdig[N], ini[22];
    
    int calc(int x) {
    	int res=0;
    	while(x) {
    		if(x&1) ++res;
    		x>>=1;
    	}
    	return res;
    }
    
    int main() {
    	rep(i,0,N) cdig[i]=calc(i);
    	ini[0]=1;
    	rep(i,1,22) ini[i]=ini[i-1]*i;
    	int T;scanf("%d",&T);
    	while(T--) {
    		scanf("%d%d",&n,&m);
    		rep(i,0,n) rep(j,0,n) scanf("%d",&a[i][j]);
    		fill_n(f[0], M, 0);
    		f[0][0]=1;
    		rep(i,1,1<<n) {
    			rep(j,0,m+1) {
    				f[i][j]=0;
    				rep(k,0,n) if(i>>k&1) {
    					f[i][j]+=f[i^(1<<k)][max(0, j-a[cdig[i]-1][k])];
    				}
    			}
    		}
    		int fz=ini[n], fm=f[(1<<n)-1][m];
    		if(fm==0) {
    			puts("No solution");
    			continue;
    		}
    		int d=__gcd(fz, fm);fz/=d;fm/=d;
    		printf("%d/%d
    ",fz,fm);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    python3 bytes数据类型探讨
    字典
    列表及元组
    在py文件中设置文件头
    函数的作用域、global与nonlocal
    python中 的意义及用法
    int、bool和str
    while循环、格式化输出、运算符和编码初识
    python初认识、基础数据类型以及 if 流程控制
    列表遍历和生成器遍历效率对比
  • 原文地址:https://www.cnblogs.com/wuyuanyuan/p/9087730.html
Copyright © 2011-2022 走看看