UVa 216 - Getting in Line

36 篇文章 0 订阅

乍一看,像最小生成树,实际不用,因为数据量较小(最大8台电脑),所以直接模拟全排列算最小值就可以。

代码如下:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;

struct point
{
    int x, y;
} po[10];
int n;
double save_d[10], dis[10], tot, dd;
int max_[10], save_v[10], vis[10];
int solve(int cur, double d)
{
    if(cur == n)
    {
        if(d < tot)
        {
            tot = d;
            for(int i = 0; i < n; i++)
            {
                save_d[i] = dis[i];
                max_[i] = save_v[i];
            }
        }
        return 1;
    }
    for(int i = 0; i < n; i++)
        if(!vis[i])
        {
            if(cur)
            {
                double ans1, ans2;
                ans1 = (double)(po[i].x - po[save_v[cur - 1]].x);
                ans2 = (double)(po[i].y - po[save_v[cur - 1]].y);
                dd = sqrt(ans1 * ans1 + ans2 * ans2);
                dis[cur - 1] = dd;
            }
            else
                dd = 0;
            if(d + dd > tot) // 若中间过程中路程和已经大于已知的最小值,则直接忽略此种排列情况
                continue;
            vis[i] = 1;
            save_v[cur] = i;
            solve(cur + 1, d + dd);
            vis[i] = 0;
        }
    return 0;
}
int main()
{
#ifdef test
    freopen("sample.txt", "r", stdin);
#endif
    int num = 1;
    while(scanf("%d", &n), n)
    {
        tot = 1000000;
        memset(vis, 0, sizeof(vis));
        for(int i = 0; i < n; i++)
            scanf("%d%d", &po[i].x, &po[i].y);
        solve(0, 0);
        printf("**********************************************************\n");
        printf("Network #%d\n", num++);
        for(int i = 0; i < n - 1; i++)
            printf("Cable requirement to connect (%d,%d) to (%d,%d) is %.2lf feet.\n", po[max_[i]].x, po[max_[i]].y, po[max_[i + 1]].x, po[max_[i + 1]].y, save_d[i] + 16);
        printf("Number of feet of cable required is %.2lf.\n", tot + (n - 1) * 16);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值