NOIP 2014 提高组 复赛 第二天 第一题 无线网路发射器选址 wireless AC代码(二维差分+边界处理)+70代码(二维差分)
总目录详见:NOIP 提高组 复赛 试题 目录 信奥 历年
在线测评地址:[NOIP2014 提高组] 无线网络发射器选址
1.70代码(二维差分)
二维差分不了解,可看下文
差分 一维差分 二维差分 差分数组意义 前缀和 一维前缀和 二维前缀和
#include <bits/stdc++.h>
#define LL long long
using namespace std;
LL a[135][135],b[135][135],mx;//b[x][x]表示以(x,y)位置为发射器,所能覆盖的数量
int main(){
int d,n,x,y,k,i,j,x1,y1,x2,y2,x3,y3,x4,y4,cnt;
scanf("%d%d",&d,&n);
for(i=0;i<=128;i++)
for(j=0;j<=128;j++)
a[i][j]=0;
for(i=1;i<=n;i++)
scanf("%d%d%d",&x,&y,&k),a[x][y]=k;
for(x=1;x<=128;x++)a[x][0]+=a[x-1][0];//第0行上求和
for(y=1;y<=128;y++)a[0][y]+=a[0][y-1];//第0列上求和
for(x=1;x<=128;x++)
for(y=1;y<=128;y++)
a[x][y]+=a[x][y-1]+a[x-1][y]-a[x-1][y-1];
mx=0,cnt=0;
for(x=0;x<=128;x++)
for(y=0;y<=128;y++){
x1=x-d-1,y1=y-d-1;//此处要注意不是x1=x-d,y1=y-d;
x4=x+d,y4=y+d;
if(x1<0)x1=0;
if(y1<0)y1=0;
if(x4>128)x4=128;
if(y4>128)y4=128;
x2=x4,y2=y1;
x3=x1,y3=y4;
b[x][y]=a[x4][y4]-a[x2][y2]-a[x3][y3]+a[x1][y1];
if(mx<b[x][y])mx=b[x][y];
}
for(x=0;x<=128;x++)
for(y=0;y<=128;y++)
if(b[x][y]==mx)cnt++;
printf("%d %lld\n",cnt,mx);
return 0;
}
上述代码70分的原因是,发射器处于道路的边界时,矩阵运算会有问题,具体可看如下测试样例,以下数据为正确数据
INPUT:
1
1
0 0 1
OUTPUT:
4 1
2.AC代码(二维差分+边界处理)
在70分代码的基础上,将x坐标整体右移一个单位,将y坐标整体下移一个单位,并做好边界的处理,请仔细比对代码。
#include <bits/stdc++.h>
#define LL long long
using namespace std;
LL a[135][135],b[135][135],mx;//b[x][x]表示以(x,y)位置为发射器,所能覆盖的数量
int main(){
int d,n,x,y,k,i,j,x1,y1,x2,y2,x3,y3,x4,y4,cnt;
scanf("%d%d",&d,&n);
for(i=0;i<=128+1;i++)
for(j=0;j<=128+1;j++)
a[i][j]=0;
for(i=1;i<=n;i++)
scanf("%d%d%d",&x,&y,&k),a[x+1][y+1]=k;
for(x=1;x<=128;x++)a[x+1][0+1]+=a[x-1+1][0+1];//第0行上求和
for(y=1;y<=128;y++)a[0+1][y+1]+=a[0+1][y-1+1];//第0列上求和
for(x=1;x<=128;x++)
for(y=1;y<=128;y++)
a[x+1][y+1]+=a[x+1][y-1+1]+a[x-1+1][y+1]-a[x-1+1][y-1+1];
mx=0,cnt=0;
for(x=0+1;x<=128+1;x++)
for(y=0+1;y<=128+1;y++){
x1=x-d-1,y1=y-d-1;//此处要注意不是x1=x-d,y1=y-d;
x4=x+d,y4=y+d;
if(x1<0)x1=0;
if(y1<0)y1=0;
if(x4>128+1)x4=128+1;
if(y4>128+1)y4=128+1;
x2=x4,y2=y1;
x3=x1,y3=y4;
b[x][y]=a[x4][y4]-a[x2][y2]-a[x3][y3]+a[x1][y1];
if(mx<b[x][y])mx=b[x][y];
}
for(x=0+1;x<=128+1;x++)
for(y=0+1;y<=128+1;y++)
if(b[x][y]==mx)cnt++;
printf("%d %lld\n",cnt,mx);
return 0;
}