通信基站(dfs回溯,思维)

Description

Input

Output

Sample Input

2 2 1 1 0 0 4 4 3 100 1 0 0 1 1 500 500

Sample Output

2.00 201.41
题解:用容斥的方法,选出所有情况,对于每种情况把选好的点和未选好的点分别放在两个集合中,对于未匹配的点搜索找区间覆盖这个点的最大距离,回溯当前距离;在结果中找最小值;
AC代码:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int INF=0xfffffff;
#define mem(x,y) memset(x,y,sizeof(x))
#define SI(x) scanf("%d",&x)
#define PI(x) printf("%d",x)
typedef long long LL;
const int MAXN=110;
double lx[MAXN],ly[MAXN];
double mp[MAXN][MAXN];
int N,ta,tb;
int a[MAXN],b[MAXN];
double ans,sum;
double C,R;
double d[MAXN];
double getl(int i,int j){
    double y=ly[j]-ly[i],x=lx[j]-lx[i];
    return sqrt(x*x+y*y);
}
void solve(int m){
    if(m==0){
        double res=0;
        for(int i=0;i<N;i++)res+=d[i];
        sum=min(sum,res);
        return;
    }
    for(int i=0;i<tb;i++){
        double x=getl(a[m-1],b[i]);
        double val=d[i];
        d[i]=max(d[i],x);//
        solve(m-1);
        d[i]=val;//
    }
}
void work(){
    ans=INF;
    for(int i=1;i<(1<<N);i++){
        double temp=0;
        ta=tb=0;
        mem(d,0);
        for(int j=0;j<N;j++){
            if(i&(1<<j)){
                temp+=C;
                b[tb++]=j;
            //    printf("%d ",j);
            }
            else a[ta++]=j;
        }
        //puts("");
        //for(int k=0;k<N;k++)printf("d[%d]=%.1lf ",k,d[k]);puts("");
        sum=INF;
        solve(ta);
        ans=min(ans,temp+R*sum);
    }
    printf("%.2f
",ans);
}
int main(){
    int T;
    SI(T);
    while(T--){
        scanf("%d%lf%lf",&N,&C,&R);
        for(int i=0;i<N;i++){
            scanf("%lf%lf",&lx[i],&ly[i]);
        }
        for(int i=0;i<N;i++)
            for(int j=i+1;j<N;j++)
                mp[i][j]=mp[j][i]=getl(i,j);
            work();
    }
    return 0;
}

刚开始没考虑太多,之所以wa,因为我只是对每个点找到已经选的点的最小距离,由于这是雷达,已选的点可以覆盖多个未选的点,那么距离就是最大的那个距离,而我的可能会重复;

WA代码:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int INF=0xfffffff;
#define mem(x,y) memset(x,y,sizeof(x))
#define SI(x) scanf("%d",&x)
#define PI(x) printf("%d",x)
typedef long long LL;
const int MAXN=110;
double lx[MAXN],ly[MAXN];
double mp[MAXN][MAXN];
int N;
double ans;
double C,R;
double d[MAXN];
double getl(int i,int j){
    double y=ly[j]-ly[i],x=lx[j]-lx[i];
    return sqrt(x*x+y*y);
}
void work(){
    ans=INF;
    for(int i=1;i<(1<<N);i++){
        double temp=0;
        for(int k=0;k<N;k++)d[k]=INF;
        for(int j=0;j<N;j++){
            if(i&(1<<j)){
                temp+=C;
                for(int k=0;k<N;k++){
                    d[k]=min(d[k],R*mp[k][j]);
                }
                d[j]=0;
            //    printf("%d ",j);
            }
        }
        //puts("");
        for(int i=0;i<N;i++)temp+=d[i];
        //for(int k=0;k<N;k++)printf("d[%d]=%.1lf ",k,d[k]);puts("");
        ans=min(ans,temp);
    }
    printf("%.2f
",ans);
}
int main(){
    int T;
    SI(T);
    while(T--){
        scanf("%d%lf%lf",&N,&C,&R);
        for(int i=0;i<N;i++){
            scanf("%lf%lf",&lx[i],&ly[i]);
        }
        for(int i=0;i<N;i++)
            for(int j=i+1;j<N;j++)
                mp[i][j]=mp[j][i]=getl(i,j);
            work();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/handsomecui/p/5232340.html