HDU 2489 Minimal Ratio Tree (暴力枚举+最小生成树)

来源:互联网 发布:淘宝店面怎样装修模板 编辑:程序博客网 时间:2024/05/17 04:44

题目链接:HDU 2489 Minimal Ratio Tree

题意:给出n,m,n个点的点权和一个n*n的矩阵,(i,j)表示点i到点j的比边权为(i,j),在n个点中选m个点,求最小的ratio。(ratio = 所有边权和/所有点权和)

思路:n最大15,状态压缩每个点是否取,再用Prim得到最小的边权,即得到ratio;


AC代码:


#include <stdio.h>#include <set>#include <string.h>#include <algorithm>using namespace std;const int maxn = 30;const int inf = 999999999;double minans;int vis[maxn];//记录选中的点int mp[maxn][maxn],ans[maxn][maxn];int min_road[maxn];int Prim(int n){int i,j,min_i,min,sum=0;int dis[maxn];int vis[maxn];for(i=1;i<=n;i++)dis[i]=ans[i][1];memset(vis,false,sizeof vis);vis[1]=true;for(i=1;i<n;i++){min=inf,min_i=i;for(j=1;j<=n;j++){if(vis[j]==false && dis[j]<min){min=dis[j];min_i=j;}}if(min==inf)break;sum+=min;vis[min_i]=true;for(j=1;j<=n;j++){if(vis[j]==0 && dis[j]>ans[min_i][j])dis[j]=ans[min_i][j];}}return sum;}int ok(int n){memset(vis, 0, sizeof vis);int cnt = 1;int m = n, cont = 1;while(m){if(m%2)vis[cont++]=cnt;cnt++;m /= 2;}return cont;}int main(){int d[maxn],maxm;int n, i, j, k, cnt, m;while(scanf("%d%d",&n,&m)!=EOF){if(n == 0 && m == 0)break;maxm = 1;for(i = 1; i <= n; i++)maxm *= 2;for(i = 1; i <= n; i++)scanf("%d", &d[i]);for(i = 1; i <= n; i++){for(j = 1; j <= n ; j++){scanf("%d",&mp[i][j]);}}minans = 9999999999.0;int sum_point;for(i = 0; i < maxm; i++){if(ok(i) == m+1){sum_point = 0;for(j = 1; j <= m; j++){sum_point += d[vis[j]];//选的点。for(k = j+1; k <= m; k++){ans[j][k] = ans[k][j] = mp[vis[j]][vis[k]];}}int sum = Prim(m);if((sum*1.0 / sum_point) < minans){ minans = sum*1.0 / sum_point; for(i = 1; i<= m; i++) min_road[i] = vis[i];}}}for(i = 1; i<= m-1; i++)printf("%d ",min_road[i]);printf("%d\n",min_road[i]);}return 0;}/*3 230 20 100 6 26 0 32 3 03 330 20 100 6 26 0 32 3 03 210 10 100 1 11 0 11 1 0*/


0 0