Source: 2016-2017 ACM-ICPC, Egyptian Collegiate Programming Contest (ECPC 16)
Problem:
n∗n
的棋盘上有
m
个棋子,每个棋子
Idea: 很明显,依次考虑棋盘上的每条对角线。不等式移项后, 1+xi−p2i−C≥xj+p2j , 则每个物品i具有两个属性,即 (1+xi−p2i−C) 和 (xi+p2i) ,将其按照 (xi+p2i) 的大小排序后,发现物品的大小关系是具有传递性的,DP或者直接贪心就可以了。
Code:
#include<bits/stdc++.h>
using namespace std;
//#define LOCAL
#define fi first
#define se second
#define pb push_back
#define ALL(A) (A).begin(), (A).end()
#define CLR(A, X) memset(A, X, sizeof(A))
typedef long long LL;
typedef pair<LL, LL> PII;
const double eps = 1e-10;
const double PI = acos(-1.0);
const auto INF = 0x3f3f3f3f;
int dcmp(double x) { if(fabs(x) < eps) return 0; return x<0?-1:1; }
const int MAXN = 4e5+5;
vector<PII> G[MAXN];
int main() {
#ifndef LOCAL
freopen("bishops.in", "r", stdin);
#endif // LOCAL
int X;
scanf("%d", &X);
while(X--) {
int n, m, C;
scanf("%d%d%d", &n, &m, &C);
while(m--) {
int x, y; LL p;
scanf("%d%d%lld", &x, &y, &p);
p *= p;
G[x+y-2].pb({x+p, 1+x-p-C});
G[x-y-2+3*n].pb({x+p, 1+x-p-C});
}
int ans = 0;
for(int k = 0; k < 4*n; k++) if(G[k].size()) {
sort(ALL(G[k]));
int j = 0, t = 0;
for(int i = 0; i < G[k].size(); i++) {
if(G[k][i].se >= G[k][j].fi) {
t++;
j = i;
}
}
ans = max(ans, t);
}
printf("%d\n", ans+1);
for(int i = 0; i <= 4*n; i++) G[i].clear();
}
return 0;
}