uva 216 - Getting in Line

给出n个结点的横纵坐标,将它们连成一条线,怎么样使他们的的距离最小。

用回朔法,以任意一个为起点,先连到最后一个,然后回朔。

若比当前最小值小,则用数组记录路线。

#include<cstdio>
#include<cstring>
#include<cmath>
const int MAXN=10;
double dis(int x1,int y1,int x2,int y2){
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
typedef struct{
    int x,y,father;
    double dis;
}solve;
solve a[MAXN];
int minf[MAXN],minfather,n;             //最后一个结点,数组记录最佳结点的路线
double ans,temp,mindis[MAXN];
bool vis[MAXN];
void input(int n,int cur){              //递归输出有路线
    if(cur==0) return ;
    input(minf[n],cur-1);
    printf("Cable requirement to connect (%d,%d) to (%d,%d) is %.2f feet.\n",a[minf[n]].x,a[minf[n]].y,a[n].x,a[n].y,mindis[n]);
}
void dfs(int cur,int father){
    if(temp>ans) return ;
    if(cur==n){
        if(temp<=ans) {
            ans=temp;
            minfather=father;
            for(int i=0;i<n;i++) {              //记得更新路线
                mindis[i]=a[i].dis;
                minf[i]=a[i].father;
            }
        }
        return ;
    }
    else for(int i=0;i<n;i++) if(!vis[i]){
        if(father!=-1) a[i].dis = dis(a[i].x,a[i].y,a[father].x,a[father].y)+16;            //电缆的长度比距离多16
        else a[i].dis=0;
        a[i].father=father;
        vis[i]=true;
        temp+=a[i].dis;
        dfs(cur+1,i);
        vis[i]=false;
        temp-=a[i].dis;                     //注意回朔
    }
}
int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int cnt=0;
    while(~scanf("%d",&n)){
        ans=1000000;
        if(n==0) break;
        memset(vis,false,sizeof(vis));
        for(int i=0;i<n;i++) scanf("%d%d",&a[i].x,&a[i].y);
        dfs(0,-1);
        printf("**********************************************************\n");
        cnt++; printf("Network #%d\n",cnt);
        input(minfather,n-1);
        printf("Number of feet of cable required is %.2f.\n",ans);
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值