hdu2489 Minimal Ratio Tree dfs枚举组合情况+最小生成树

  1 #include <stdio.h>
  2 #include <set>
  3 #include <string.h>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 const int maxn = 30;
  8 const int inf = 999999999;
  9 double minans;
 10 int vis[maxn];//记录选中的点
 11 int mp[maxn][maxn], ans[maxn][maxn];
 12 int min_road[maxn];
 13 
 14 int Prim(int n)
 15 {
 16     int i, j, min_i, minm, sum = 0;
 17     int dis[maxn];
 18     int vis[maxn];
 19     for (i = 1; i <= n; i++)
 20         dis[i] = ans[i][1];
 21     memset(vis, false, sizeof vis);
 22     vis[1] = true;
 23     for (i = 1; i<n; i++)
 24     {
 25         minm = inf, min_i = i;
 26         for (j = 1; j <= n; j++)
 27         {
 28             if (vis[j] == false && dis[j]<minm)
 29             {
 30                 minm = dis[j];
 31                 min_i = j;
 32             }
 33         }
 34         if (minm == inf)
 35             break;
 36         sum += minm;
 37         vis[min_i] = true;
 38         for (j = 1; j <= n; j++)
 39         {
 40             if (vis[j] == 0 && dis[j]>ans[min_i][j])
 41                 dis[j] = ans[min_i][j];
 42         }
 43     }
 44     return sum;
 45 }
 46 
 47 int ok(int n)
 48 {
 49     memset(vis, 0, sizeof vis);
 50     int cnt = 1;
 51     int m = n, cont = 1;
 52     while (m)
 53     {
 54         if (m % 2)
 55             vis[cont++] = cnt;
 56         cnt++;
 57         m /= 2;
 58     }
 59     return cont;
 60 }
 61 
 62 int main()
 63 {
 64     int d[maxn], maxm;
 65     int n, i, j, k, cnt, m;
 66     while (scanf("%d%d", &n, &m) != EOF)
 67     {
 68         if (n == 0 && m == 0)
 69             break;
 70         maxm = 1;
 71         for (i = 1; i <= n; i++)
 72             maxm *= 2;
 73         for (i = 1; i <= n; i++)
 74             scanf("%d", &d[i]);
 75         for (i = 1; i <= n; i++)
 76         {
 77             for (j = 1; j <= n; j++)
 78             {
 79                 scanf("%d", &mp[i][j]);
 80             }
 81         }
 82         minans = 9999999999.0;
 83         int sum_point;
 84         for (i = 0; i < maxm; i++)
 85         {
 86             if (ok(i) == m + 1)
 87             {
 88                 sum_point = 0;
 89                 for (j = 1; j <= m; j++)
 90                 {
 91                     sum_point += d[vis[j]];//选的点
 92                     for (k = j + 1; k <= m; k++)
 93                     {
 94                         ans[j][k] = ans[k][j] = mp[vis[j]][vis[k]];
 95                     }
 96                 }
 97                 int sum = Prim(m);
 98                 if ((sum*1.0 / sum_point) < minans)
 99                 {
100                     minans = sum*1.0 / sum_point;
101                     for (i = 1; i <= m; i++)
102                         min_road[i] = vis[i];
103                 }
104             }
105         }
106         for (i = 1; i <= m - 1; i++)
107             printf("%d ", min_road[i]);
108         printf("%d\n", min_road[i]);
109     }
110     return 0;
111 }

 

转载于:https://www.cnblogs.com/ouyang_wsgwz/p/7658034.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值