zoukankan      html  css  js  c++  java
  • [洛谷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;
    }
    

    本题解已同步至洛谷博客

  • 相关阅读:
    EIGRP系统复习【转载】
    EIGRP系统复习【转载】
    EIGRP系统复习【转载】
    新CCIE笔记之'口口相传'路由协议
    新CCIE笔记之'口口相传'路由协议
    新CCIE笔记之'口口相传'路由协议
    【★】自制网络心理需求大排名!
    【★】假如人类使用16进制
    【★】假如人类使用16进制
    算法之【大整数乘法】
  • 原文地址:https://www.cnblogs.com/juruoajh/p/12673295.html
Copyright © 2011-2022 走看看