hdu 3656 Fire station 重复覆盖 DLX+二分答案 给出一些城市及一些救火站的坐标,要求这些救火站覆盖所有的城市,问从救火站到城市的最长时间至少是多少。
2011-09-16 18:02
465 查看
Problem Description
A city's map can be seen as a two dimensional plane. There are N houses in the city and these houses can be seen as N points P1 …… PN on the two dimensional plane. For simplicity's sake, assume that the time spent from one house number
to another is equal to the distance between two points corresponding to the house numbers. The government decides to build M fire stations from N houses. (If a station is build in Pi, We can think the station is next to the house and the time from the station
to the house is considered zero.) It is obvious that if some place such as Pi is breaking out of fire, the nearest station will dispatched a fire engine quickly rushed to the rescue scene. The time it takes from this station to the rescue scene is called rescue
time. Now you need to consider about a problem that how to choice the positions of the M fire station to minimize the max rescue time of all the houses.
Input
The fi rst line of the input contains one integer T, where T is the number of cases. For each case, the fi rst line of each case contains two integers N and M separated by spaces (1 ≤ M ≤N ≤ 50), where N is the number of houses and M is the number of fire stations.
Then N lines is following. The ith line contains two integers Xi and Yi (0 ≤ Xi, Yi ≤ 10000), which stands for the coordinate of the ith house.
Output
The rescue time which makes the max rescue time is minimum.
Sample Input
Sample Output
//
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define eps 1e-8
#define N 85
#define V 36000
int n,m,K;//n行 m列 K限制条件,最多用K行(仅限于此题)
int L[V],R[V];
int D[V],U[V];
int C[V];
int S
,H
;
int ak,size;//ak 最少多少行可以覆盖所有列(可重复)
double dis(double x1,double y1,double x2,double y2)
{
return sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
}
void Link(int r,int c)
{
S[c]++;C[size]=c;
U[size]=U[c];D[U[c]]=size;
D[size]=c;U[c]=size;
if(H[r]==-1) H[r]=L[size]=R[size]=size;
else
{
L[size]=L[H[r]];R[L[H[r]]]=size;
R[size]=H[r];L[H[r]]=size;
}
size++;
}
void remove(int c)
{
int i;
for(i=D[c];i!=c;i=D[i])
L[R[i]]=L[i],R[L[i]]=R[i];
}
void resume(int c)
{
int i;
for(i=U[c];i!=c;i=U[i])
L[R[i]]=R[L[i]]=i;
}
int h()
{
int i,j,k,count=0;
bool visit
;
memset(visit,0,sizeof(visit));
for(i=R[0];i;i=R[i])
{
if(visit[i]) continue;
count++;
visit[i]=1;
for(j=D[i];j!=i;j=D[j])
{
for(k=R[j];k!=j;k=R[k])
visit[C[k]]=1;
}
}
return count;
}
void Dance(int k)
{
int i,j,c,Min,ans;
ans=h();
if(k+ans>K) return ;//仅限于此题
if(k+ans>=ak) return;
if(!R[0])
{
if(k<ak) ak=k;
return;
}
for(Min=N,i=R[0];i;i=R[i])
if(S[i]<Min) Min=S[i],c=i;
for(i=D[c];i!=c;i=D[i])
{
remove(i);
for(j=R[i];j!=i;j=R[j])
remove(j);
Dance(k+1);
for(j=L[i];j!=i;j=L[j])
resume(j);
resume(i);
}
return;
}
double d[66][66];
double dl[66*66];
int main()
{
int i,j,ncase;
double x
,y
;
int left,right,mid;
double ans;
scanf("%d",&ncase);
while(ncase--)
{
int tn;
//村庄当成列tn,救火站当成行tn 最多用K个救火站
scanf("%d%d",&tn,&K);
n=m=tn;
for(i=1;i<=m;i++)
scanf("%lf%lf",&x[i],&y[i]);
int num = 0;
for (i = 1; i <= n; ++i) {
for (j = i; j <= m; ++j) {
d[i][j] = d[j][i] = dl[num++] = dis(x[i],y[i],x[j], y[j]);
}
}
//二分答案这里要注意:如果直接left=0,right=(1<<30)直接二分 会超时
//这里要把所有距离先排序 二分枚举这些距离 AC
sort(dl, dl + num);
num = unique(dl, dl + num) - dl;
left=0;
right= num-1;
ans=dl[right];
while(left<right)
{
//DLX
for(i=0;i<=m;i++)
{
S[i]=0;
U[i]=D[i]=i;
L[i+1]=i;R[i]=i+1;
}R[m]=0;
memset(H,-1,sizeof(H));
size=m+1;
mid=(left+right)/2;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
if(dl[mid]>=d[i][j]) Link(i,j);
}
ak=N;
Dance(0);
//......
if(ak<=K) {ans=min(ans,dl[mid]);right=mid;}
else left=mid+1;
}
printf("%.6lf\n",ans);
}
return 0;
}
A city's map can be seen as a two dimensional plane. There are N houses in the city and these houses can be seen as N points P1 …… PN on the two dimensional plane. For simplicity's sake, assume that the time spent from one house number
to another is equal to the distance between two points corresponding to the house numbers. The government decides to build M fire stations from N houses. (If a station is build in Pi, We can think the station is next to the house and the time from the station
to the house is considered zero.) It is obvious that if some place such as Pi is breaking out of fire, the nearest station will dispatched a fire engine quickly rushed to the rescue scene. The time it takes from this station to the rescue scene is called rescue
time. Now you need to consider about a problem that how to choice the positions of the M fire station to minimize the max rescue time of all the houses.
Input
The fi rst line of the input contains one integer T, where T is the number of cases. For each case, the fi rst line of each case contains two integers N and M separated by spaces (1 ≤ M ≤N ≤ 50), where N is the number of houses and M is the number of fire stations.
Then N lines is following. The ith line contains two integers Xi and Yi (0 ≤ Xi, Yi ≤ 10000), which stands for the coordinate of the ith house.
Output
The rescue time which makes the max rescue time is minimum.
Sample Input
2 4 2 1 1 1 2 2 3 2 4 4 1 1 1 1 2 2 3 2 4
Sample Output
1.000000 2.236068
//
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define eps 1e-8
#define N 85
#define V 36000
int n,m,K;//n行 m列 K限制条件,最多用K行(仅限于此题)
int L[V],R[V];
int D[V],U[V];
int C[V];
int S
,H
;
int ak,size;//ak 最少多少行可以覆盖所有列(可重复)
double dis(double x1,double y1,double x2,double y2)
{
return sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
}
void Link(int r,int c)
{
S[c]++;C[size]=c;
U[size]=U[c];D[U[c]]=size;
D[size]=c;U[c]=size;
if(H[r]==-1) H[r]=L[size]=R[size]=size;
else
{
L[size]=L[H[r]];R[L[H[r]]]=size;
R[size]=H[r];L[H[r]]=size;
}
size++;
}
void remove(int c)
{
int i;
for(i=D[c];i!=c;i=D[i])
L[R[i]]=L[i],R[L[i]]=R[i];
}
void resume(int c)
{
int i;
for(i=U[c];i!=c;i=U[i])
L[R[i]]=R[L[i]]=i;
}
int h()
{
int i,j,k,count=0;
bool visit
;
memset(visit,0,sizeof(visit));
for(i=R[0];i;i=R[i])
{
if(visit[i]) continue;
count++;
visit[i]=1;
for(j=D[i];j!=i;j=D[j])
{
for(k=R[j];k!=j;k=R[k])
visit[C[k]]=1;
}
}
return count;
}
void Dance(int k)
{
int i,j,c,Min,ans;
ans=h();
if(k+ans>K) return ;//仅限于此题
if(k+ans>=ak) return;
if(!R[0])
{
if(k<ak) ak=k;
return;
}
for(Min=N,i=R[0];i;i=R[i])
if(S[i]<Min) Min=S[i],c=i;
for(i=D[c];i!=c;i=D[i])
{
remove(i);
for(j=R[i];j!=i;j=R[j])
remove(j);
Dance(k+1);
for(j=L[i];j!=i;j=L[j])
resume(j);
resume(i);
}
return;
}
double d[66][66];
double dl[66*66];
int main()
{
int i,j,ncase;
double x
,y
;
int left,right,mid;
double ans;
scanf("%d",&ncase);
while(ncase--)
{
int tn;
//村庄当成列tn,救火站当成行tn 最多用K个救火站
scanf("%d%d",&tn,&K);
n=m=tn;
for(i=1;i<=m;i++)
scanf("%lf%lf",&x[i],&y[i]);
int num = 0;
for (i = 1; i <= n; ++i) {
for (j = i; j <= m; ++j) {
d[i][j] = d[j][i] = dl[num++] = dis(x[i],y[i],x[j], y[j]);
}
}
//二分答案这里要注意:如果直接left=0,right=(1<<30)直接二分 会超时
//这里要把所有距离先排序 二分枚举这些距离 AC
sort(dl, dl + num);
num = unique(dl, dl + num) - dl;
left=0;
right= num-1;
ans=dl[right];
while(left<right)
{
//DLX
for(i=0;i<=m;i++)
{
S[i]=0;
U[i]=D[i]=i;
L[i+1]=i;R[i]=i+1;
}R[m]=0;
memset(H,-1,sizeof(H));
size=m+1;
mid=(left+right)/2;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
if(dl[mid]>=d[i][j]) Link(i,j);
}
ak=N;
Dance(0);
//......
if(ak<=K) {ans=min(ans,dl[mid]);right=mid;}
else left=mid+1;
}
printf("%.6lf\n",ans);
}
return 0;
}
相关文章推荐
- hdu 2295 Radar 重复覆盖 DLX+二分答案 给出一些城市及一些雷达的坐标,要求从这些雷达中选取最多k个能够覆盖所有的城市,问雷达的最小覆盖半径为多少
- HDU 3656 Fire station(巧妙的二分+DLX重复覆盖)
- 素数距离问题 时间限制:3000 ms | 内存限制:65535 KB 难度:2 描述 现在给出你一些数,要求你写出一个程序,输出这些整数相邻最近的素数,并输出其相距长度。如果左右有等距离长度素数
- hdu 3529 Bomberman - Just Search 重复覆盖+DLX 炸弹人游戏中,问最少需要放多少颗炸弹,才能够将所有的墙壁炸掉,其中,炸弹在同一时间引爆
- hdu 3498 whosyourdaddy 重复覆盖+DLX 每次攻击i和i的所有邻居,最少攻击多少人才能杀死所有敌人
- [DLX重复覆盖] hdu 3656 Fire station
- hdu 2295 dlx重复覆盖+二分答案
- 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
- (中等) HDU 2295 , DLX+重复覆盖+二分。
- hdu 2295 Radar (二分答案+重复覆盖)
- 谷歌面试题--一个大小为n的数组,里面的数都属于范围[0, n-1],有不确定的重复元素,找到至少一个重复元素,要求O(1)空间和O(n)时间
- [DLX反复覆盖] hdu 3656 Fire station
- HDU 2295 Radar (DLX可重复覆盖+二分)
- Hdu 2295 (二分+重复覆盖问题 Dancing Links)
- [ACM] HDU 2295 Radar (二分+DLX 重复覆盖)
- 现在给出你一些数,要求你写出一个程序,输出这些整数相邻最近的素数,并输出其相距长度。如果左右有等距离长度素数,则输出左侧的值及相应距离。 如果输入的整数本身就是素数,则输出该素数本身,
- 【HDU】2295 Radar 二分+重复覆盖
- 快速查找素数 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 现在给你一个正整数N,要你快速的找出在2.....N这些数里面所有的素数。 输入 给出一个正整数数N(N<=
- POJ1743 Musical Theme,后缀数组,最长重复不重叠子串,二分检索答案
- HDU 5046 Airport (DLX可重复覆盖+二分)