您的位置:首页 > 理论基础 > 计算机网络

洛谷 P2038 无线网络发射器选址

2017-10-13 19:26 176 查看


题目描述

随着智能手机的日益普及,人们对无线网的需求日益增大。某城市决定对城市内的公共场所覆盖无线网。

假设该城市的布局为由严格平行的129 条东西向街道和129 条南北向街道所形成的网格状,并且相邻的平行街道之间的距离都是恒定值 1 。东西向街道从北到南依次编号为0,1,2…128 , 南北向街道从西到东依次编号为0,1,2…128 。

东西向街道和南北向街道相交形成路口,规定编号为x 的南北向街道和编号为y 的东西向街道形成的路口的坐标是(x , y )。 在 某 些 路口存在一定数量的公共场所 。

由于政府财政问题,只能安装一个大型无线网络发射器。该无线网络发射器的传播范围

一个以该点为中心,边长为2*d 的正方形。传播范围包括正方形边界。

例如下图是一个d = 1 的无线网络发射器的覆盖范围示意图。



现在政府有关部门准备安装一个传播参数为d 的无线网络发射器,希望你帮助他们在城市内找出合适的安装地点,使得覆盖的公共场所最多。

输入输出格式

输入格式:

输入文件名为wireless.in。

第一行包含一个整数d ,表示无线网络发射器的传播距离。

第二行包含一个整数n ,表示有公共场所的路口数目。

接下来n 行,每行给出三个整数x , y , k , 中间用一个空格隔开,分别代表路口的坐标( x , y )

以及该路口公共场所的数量。同一坐标只会给出一次。

输出格式:

输出文件名为wireless.out 。

输出一行,包含两个整数,用一个空格隔开,分别表示能覆盖最多公共场所的安装地点 方案数,以及能覆盖的最多公共场所的数量。

输入输出样例

输入样例#1:

1  

2  

4 4 10  

6 6 20  

 输出样例#1:

1 30

说明

对于100%的数据,1≤d≤20,1≤n≤20, 0≤x≤128,0≤y≤128,0<k≤1,000,000。

题解:两个方法:前缀和、差分,对于每个点(128*128个点)考虑在每个点安装能够覆盖的最大范围,如果暴力枚举显然会超时,所以用一个前缀和优化。分析一个规律,当几个点能够被同时覆盖时,那么以其中任意一个点为安装点其余的点均可以被覆盖,那么只需要找被最多覆盖的点即可,由于点具有连续性,所以可以用差分的方法来做。

总结:对于覆盖问题既可以从正面分析,去覆盖,也可以反面分析,被覆盖。两种不同
4000
的分析可以用不同的方法来做。对于差分,一定要有广义的认识,只要具有连续性,就可以考虑差分,但要注意的是差分合并时的顺序!!!
/*//前缀和思想
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
int D,n;
int dp[300][300],a[300][300];
int main(){
int x,y,k;
scanf("%d%d",&D,&n);
while(n--){
scanf("%d%d%d",&x,&y,&k);
a[x+1][y+1]=k;
}
for(int i=1;i<=129;i++)
for(int j=1;j<=129;j++)
dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+a[i][j];
int xx=0,ans=-10000,num=0;
for(int i=1;i<=129;i++){
for(int j=1;j<=129;j++){
xx=dp[min(i+D,129)][min(j+D,129)]-dp[max(i-D-1,0)][min(j+D,129)]-dp[min(i+D,129)][max(j-D-1,0)]+dp[max(i-D-1,0)][max(j-D-1,0)];
if(xx==ans) num++;
else if(xx > ans) ans=xx,num=1;
}
}
printf("%d %d\n",num,ans);
return 0;
}

#include<iostream>
using namespace std;
long long d,ii,jj,n,x,y,k,a[1001][1001],s[1001][1001],b[100001]={0},ans,sum,t;
int main()
{
int cm=0;
cin>>d>>n;
for(int i=1;i<=n;i++)
{
cin>>x>>y>>k;
a[x+100][y+100]=k;
}
for(int i=100;i<=250;i++)
for(int j=100;j<=250;j++)
s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
for(int i=100;i<=228;i++)
for(int j=100;j<=228;j++)
{
cm=s[i+d][j+d]-s[i-d-1][j+d]-s[i+d][j-d-1]+s[i-d-1][j-d-1];
if(cm==ans) sum++;
else if(cm>ans) ans=cm,sum=1;
}
cout<<sum<<" "<<ans;
return 0;
}
putin
1
11
0 0 10
64 64 10
0 124 5
4 128 5
3 128 1
0 128 4
128 128 10
127 0 10
128 64 10
64 128 9
30 20 10
putout
38 10
*/
//差分的思想
/*#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
int n,D,dp[300][300];
int main(){
int x,y,k,lx,rx,ly,ry;
scanf("%d%d",&D,&n);
while(n--){
scanf("%d%d%d",&x,&y,&k);x++;y++;
lx=max(x-D,0);rx=x+D;
ly=max(y-D,0);ry=y+D;
for(int i=lx;i<=rx;i++) dp[i][ly]+=k,dp[i][ry+1]-=k;
}
int ans=-10000,sum=0;
for(int i=1;i<=129;i++){
for(int j=1;j<=129;j++){
dp[i][j]+=dp[i][j-1];
if(dp[i][j] > ans) ans=dp[i][j],sum=1;
else if(dp[i][j]==ans) sum++;
}
}
printf("%d %d\n",sum,ans);
return 0;
}
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: