通信基站(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\n",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\n",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; }