Chessforces is coming into a great war. The Knights Alliance is aiming to attack the Bishops Alliance land, it is up to you to help bishops defending their homeland.
In order to defeat the attacking knights, bishops want to make their defense line as big as possible. Defense line is a set of bishops on the chessboard where each pair of bishops in this set satisfies OK relation. OK relation between bishop i and bishop j is satisfied if they are on the same diagonal and the number of squares on the diagonal path between i and j is at least equal to pi2 + pj2 + C, where pk is privacy distance for bishop k and it is given for each bishop on the board, C is a given constant. Note that the path between two bishops includes both bishops squares.
Given the coordinates of each bishop on the chessboard, help them to find the defense line with maximum number of bishops.
First line contains number of test cases T. Each test case contains one line with (0 < n ≤ 105) size of the chessboard edge, (0 < m ≤ 105) number of bishops and the constant (0 ≤ C ≤ 105) then m line follows, the ith line of them contains three integers: (1 ≤ ri, ci, pi ≤ n) where (ri,ci) is row number and column number of the ith bishop and pi is the privacy of the ith bishop.
Print a single integer, the size of the defense line with maximum number of bishops.
1 8 5 2 7 7 1 4 4 1 3 5 1 2 6 2 4 8 1
2
Large I/O files. Please consider using fast input/output methods.
First test case explanation, columns go from left to right and rows go up to bottom, bishops labeled with borders are included in the defense line.

先把每一对角线上的点都记录下来,然后可以把每个点看为一个线段区间,这个区间的范围也就是[ xi- ( pi*pi+c/2+0.5 ) , xi + ( pi*pi+c/2+0.5 ) ] 这样只要两个区间不相交,就可以保证满足“OK relation”
然后就是对于每条对角线贪心求最大不相交区间覆盖
调了半天看了题解才知道要“
并且大牛们用的区间都是[ xi- ( pi*pi) , xi + ( pi*pi) ] 因为那些项都是常数,可以在贪心时判断条件稍微改一下
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<functional>
#include<vector>
using namespace std;
struct node
{
int x;
double p;
};
double c;
int cmp(node a,node b)
{
double s1=a.p+c/2-0.5,s2=b.p+c/2-0.5;
if(1.0*a.x-s1==1.0*b.x-s2)
return a.x+s1<b.x+s2;
return 1.0*a.x-s1<1.0*b.x-s2;
}
vector<node>w[200005],v[200005];
int main()
{
freopen("bishops.in","r",stdin);
int T,t,n,m,i,ans,j,x,y;
double p;
node point;
scanf("%d",&T);
while(T--)
{
ans=0;
scanf("%d %d %lf",&n,&m,&c);
for(i=0;i<=2*n+1;i++)
{
w[i].clear();
v[i].clear();
}
for(i=0;i<m;i++)
{
scanf("%d %d %lf",&x,&y,&p);
p*=p;
point.x=x;
point.p=p;
w[x-y+n].push_back(point);
v[x+y-1].push_back(point);
}
for(i=0;i<=2*n;i++)
{
sort(w[i].begin(),w[i].end(),cmp);
int t=0;
node po;
double ri;
for(j=0;j<w[i].size();j++)
{
po=w[i][j];
double s=po.p+c*1.0/2-0.5;
if(j==0)
{
t=1;
ri=po.x+s;
continue;
}
if(ri<=1.0*po.x-s)
{
t++;
ri=po.x+s;
}
else
{
ri=min(ri,po.x+s);
}
}
ans=max(ans,t);
}
//其实完全可以用三维vector嵌套一层循环,代码比较简练
for(i=0;i<=2*n;i++)
{
sort(v[i].begin(),v[i].end(),cmp);
int t=0;
node po;
double ri;
for(j=0;j<v[i].size();j++)
{
po=v[i][j];
double s=po.p+c*1.0/2-0.5;
if(j==0)
{
t=1;
ri=po.x+s;
continue;
}
if(ri<=1.0*po.x-s)
{
t++;
ri=po.x+s;
}
else
{
ri=min(ri,po.x+s);
}
}
ans=max(ans,t);
}
printf("%d\n",ans);
}
return 0;
}

本文介绍了一个棋盘防御问题,通过构建算法帮助象棋中的主教角色最大化其防御线,确保在给定隐私距离和常数的情况下,任意两个主教位于同一对角线上且满足特定的距离约束。
322

被折叠的 条评论
为什么被折叠?



