• [洛谷P1559][题解]运动员最佳匹配问题


    宣传

    我的博客园

    题解

    题目戳我

    0.一些想说的话

    布置的作业里有这道题,做完后发现题解好少……而且很多都是用了KM最佳匹配等我这种蒟蒻看不懂的算法,于是我就来写了这篇题解。如有雷同,纯属巧合。

    1.思路

    做这道题的大家应该已经发现了:(1leq nleq 20)
    这种数据范围,不是状压就是爆搜。这里我们选择搜索解决本题(还不是因为状压不熟练

    2.实现

    既然是搜索,那么肯定有一个顺序。我选择的是枚举男的,搜女的。

    3.剪枝&&细节

    爆搜肯定是过不去的,我们考虑剪枝。
    这道题可以采用一种类似A*的剪枝方式,令(h[i])为第(i)个男运动员能匹配到的最大竞赛优势,在搜索函数内枚举,如果所有最大的加起来都不够之前得到的(ans),那么就可以直接跳出了。

    代码

    前面的缺省源因为太长省略了,具体可以去我的博客里找

    #define N 30
    int n,ans,p[N][N],q[N][N],h[N],vis[N];
    //p,q:如题意所示 
    //h:题解里提到的估价数组 
    //vis:搜索用的 
    void DFS(int now,int sum){
    	//now:当前枚举到的男运动员 
    	//sum:当前的总竞赛优势 
    	if(now>n){//枚举完了 
    		ans=max(ans,sum);
    		return;
    	}
    	int hstar=0;
    	for(rg int i=now;i<=n;i++){
    		hstar+=h[i];
    	}
    	//如果之后的都取最大也达不到就返回 
    	if(sum+hstar<ans)return;
    	for(rg int i=1;i<=n;i++){
    		if(!vis[i]){
    			vis[i]=1;
    			//枚举下一个,一定要注意顺序! 
    			DFS(now+1,sum+p[now][i]*q[i][now]);
    			vis[i]=0;
    		}
    	}
    }
    int main(){
    	//读入部分 
    	Read(n);
    	for(rg int i=1;i<=n;i++){
    		for(rg int j=1;j<=n;j++){
    			Read(p[i][j]);
    		}
    	}
    	for(rg int i=1;i<=n;i++){
    		for(rg int j=1;j<=n;j++){
    			Read(q[i][j]);
    		}
    	}
    	//提前算出h数组,计算方式如题解所说 
    	for(rg int i=1;i<=n;i++){
    		for(rg int j=1;j<=n;j++){
    			h[i]=max(h[i],p[i][j]*q[j][i]);
    		}
    	}
    	DFS(1,0);
    	cout<<ans<<endl;//圆满结束 
    	return 0;
    }
    

    本题解已同步至洛谷博客

  • 相关阅读:
    Trie
    [转]Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)
    [Bzoj2242]常见数值算法
    JavaScript百炼成仙(记录笔记)
    tcpreplay重放报文,tcpdump能抓到包,应用程序收不到包
    用jquery tools来实现选项卡
    ExtNet第二篇
    线性表最简单的表示
    c语言中线性表基本操作方法
    ExtNet第一篇
  • 原文地址:https://www.cnblogs.com/juruoajh/p/12673295.html
Copyright © 2020-2023  润新知