• 【Gym100837F】Controlled Tournament(状压Dp 搜索剪枝)


    题目链接

    大意

    现有(N)个人要打比赛,知道任意两个人间打比赛的胜负关系。
    要求在 深度最小 的情况下,根为(M)的 竞赛树 的个数。

    满足(1le Mle Nle 16)

    思路

    虑及(N)如此之小的范围,不是状压就是暴搜。
    考虑状态(Dp[s][u][d])表示在以点集(s)组成子树,(u)为根,深度不超过(d)的方案数。
    那么转移就为(Dp[s][u][d]=Dp[s'][u][d]+Dp[s-s'][v][d]).其中(u)能击败(v)

    然而,这样做的复杂度是(O(3^N imes N^2)),考虑变成记忆化搜索省掉无用状态。

    考虑题目中给出的深度最小的条件,那么这棵树的深度一定是(left lceil log2(N) ight ceil),那么它的两棵子树深度一定都不会超过(left lceil log2(N)-1 ight ceil)
    所以记搜时,对深度不符合的子树剪枝就行了,这样的话,搜索深度肯定就只能在(left lceil log2(N) ight ceil)以内,就可以过了。

    代码

    要用Freopen

    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int MAXN=17;
    int N,M,A[MAXN][MAXN];
    int vis[MAXN],Q[MAXN],Len;
    int Cnt[1<<MAXN],H[MAXN];
    vector<int>P[MAXN];
    long long Dp[1<<(MAXN-1)][MAXN][MAXN>>1];
    int lowbit(int x){return x&(-x);}
    long long DFS(int S,int rt,int dep){
    	if(Dp[S][rt][dep]!=-1)return Dp[S][rt][dep];
    	long long &ret=(Dp[S][rt][dep]=0);
    	if(Cnt[S]==1){
    		if(S&(1<<(rt-1)))return ret=1;
    		return ret=0;
    	}
    	for(int x=S&(S-1);x;x=S&(x-1)){//其实对于枚举子集可以优化.
    		int y=S-x;
    		if(!(x&(1<<(rt-1))))continue;
    		if(H[Cnt[x]]>dep-1)continue;
    		if(H[Cnt[y]]>dep-1)continue;
    		long long Ans1=0,Ans2=0;
    		Ans1=DFS(x,rt,dep-1);
    		int size=P[rt].size();
    		for(int i=0;i<size;i++){
    			int v=P[rt][i];
    			if(!(y&(1<<(v-1))))continue;
    			Ans2+=DFS(y,v,dep-1);
    		}
    		ret+=Ans1*Ans2;
    	}
    	return ret;
    }
    int main(){
    	//freopen("f.in","r",stdin);
    	//freopen("f.out","w",stdout);
    	scanf("%d%d",&N,&M);
    	for(int i=1;i<=N;i++)
    		for(int j=1;j<=N;j++){
    			scanf("%d",&A[i][j]);
    			if(A[i][j])P[i].push_back(j);
    		}
    	for(int i=1;i<=N;i++)H[i]=ceil(log2(i));
    	for(int i=1;i<(1<<N);i++)
    		Cnt[i]=Cnt[i>>1]+(i&1);
    	memset(Dp,-1,sizeof(Dp));
    	printf("%lld
    ",DFS((1<<N)-1,M,H[N]));
    }
    
  • 相关阅读:
    Python【第三方模块&标准模块】
    Python【读写Json文件】
    python【内置函数&自定义函数】
    python【文件操作:读写文件】
    python【数据类型:列表与元组】
    QTP自传之录制
    测试工作杂谈
    心魔
    QTP自传之初识
    ActionScript学习笔记(七)——缓动和弹性运动
  • 原文地址:https://www.cnblogs.com/ftotl/p/11839637.html
Copyright © 2020-2023  润新知