zzulioj 1730: 通信基站 (全排列&DFS)好题
2016-03-01 20:45
274 查看
//原文不让粘贴。。。文章链接:http://acm.zzuli.edu.cn/zzuliacm/problem.php?id=1730
1730: 通信基站
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 35 Solved: 12
SubmitStatusWeb Board
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
1730: 通信基站
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 35 Solved: 12
SubmitStatusWeb Board
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
#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #define INF 0x3f3f3f3f3f #define ll long long #define N 11 using namespace std; double x ,y ; double r ; double sum; int a ,b ; int s ; int n,c8,cr; int ta,tb; double dis(int a,int b) { return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b])); } void dfs(int p) { int i,j; if(p==ta+1) { double res=0; for(i=1;i<=n;i++) res+=r[i];//将所有城市都覆盖的半径的和 sum=min(res,sum);//取最小的半径和 return ; } for(j=1;j<=tb;j++) { double d=dis(b[j],a[p]); double rr=r[j]; r[j]=max(r[j],d); dfs(p+1); r[j]=rr; } } double solve(int cnt)//被覆盖但却没建基站的个数 { int i,j; double res=c8*cnt;//建基站的钱 ta=tb=0; for(i=1;i<=n;i++) { if(s[i]) b[++tb]=i; else a[++ta]=i; r[i]=0; } sum=0;//如果建n个基站sum的值(半径和)就为0 if(cnt!=n) sum=INF; dfs(1); return res+sum*cr; } int main() { int t; int i,j,k; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&c8,&cr); for(i=1;i<=n;i++) scanf("%lf%lf",&x[i],&y[i]); double ans=INF; for(i=1;i<=n;i++)//建基站的个数 { memset(s,0,sizeof(s)); for(j=1;j<=i;j++) s[j]=1; while(1) { ans=min(ans,solve(i)); if(!prev_permutation(s+1,s+n+1))//判断是否进行了全排列 break; } } printf("%.2lf\n",ans); } return 0; }