洛谷 P12148 题解
我们可以顺理成章地把答案转化为作为起点的点的数量。
然后我们想一个贪心策略:对于每一列的点,它一定尽可能的从上一列靠下面的点移动过来。
感性理解就是如果你下面的点不移动到这个点,那上面的点就更没有机会了;下面的点移动到这个点,不仅增加这个点的机会,还能增加这个点同列的点的机会。
所以我们对于每一列以 \(y\) 为关键字从大到小排序。
然后按照贪心策略标记不做起点的点。
最后统计做起点的点的数量。
AC code:
#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;
typedef pair<int,int> PII;
bool cmp(PII x,PII y){
if(x.first==y.first) return x.second>y.second;
return x.first<y.first;
}
const int N=1e6+5;
PII p[N];
map<PII,int> mp;
int n,ans;
int read(){
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
signed main(){
n=read();
for(int i=1;i<=n;i++){
int x,y;
x=read(),y=read();
p[i]=make_pair(x,y);
mp[p[i]]=1;
}
sort(p+1,p+n+1,cmp);
PII nxt;
for(int i=1;i<=n;){
int x=p[i].first;
for(;p[i].first==x;i++){
if(mp[p[i]]) ans++;
int y=p[i].second;
for(int j=1;j>=-1;j--){
nxt=make_pair(x+1,y+j);
if(mp.count(nxt)&&mp[nxt]){
mp[nxt]=0;
break;
}
}
}
}
printf("%d",ans);
return 0;
}

浙公网安备 33010602011771号