题意:
给你n+1个点,组成n条边,连续的三个点之间可以构成一个三角形,现在要求你删去其中的某些点,删点的规则是删去三角形面积最小的那个三角形中间的点,直到最后剩下m+1个点。
连接:
思路:
对于每一个点,除了端点外,维护它们的三角形的面积的最小值,以及它所对应的左边相邻的点与右边相邻的点,使用优先队列对面积进行从小到大排序,每次删掉一个点,需要对其两边的三角形进行更新,再将新的两个面积加入,这个时候之前旧的面积就没用了,如果去删除会很费时,可以采用标记的方法,因为如果那个面积的左右点中有一个是不存在的点(也就是已经删除了的点)那就可以说明这个面积是错误的,则跳过,这样时间复杂度便在可接受的范围内。求三角形的面积的方法可以用叉积来求,只需要知道三个点的坐标就可以求出它的面积。
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
const int maxn=200005;
struct node
{
int x,y,idx,left,right;
double area;
bool operator < (const node b) const
{
if(area==b.area)
return idx>b.idx;
return area>b.area;
}
} points[maxn];
double get_area(int i)
{
int left=points[i].left;
int right=points[i].right;
double ax=points[left].x-points[i].x;
double ay=points[left].y-points[i].y;
double bx=points[right].x-points[i].x;
double by=points[right].y-points[i].y;
//cout << ax << ' '<< ay << ' ' << bx << ' ' << by << endl;
return 0.5*(ax*by-ay*bx);
}
priority_queue<node> Q;
bool used[maxn];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
int k=n-m;
for(int i=0; i<=n; i++)
{
scanf("%d%d",&points[i].x,&points[i].y);
points[i].idx=i;
}
memset(used,false,sizeof(used));
for(int i=1; i<n; i++)
{
points[i].left=i-1;
points[i].right=i+1;
points[i].area=fabs(get_area(i));
//cout << i << ' ' << points[i].area << endl;
Q.push(points[i]);
}
points[0].right=1;
points[n].left=n-1;/*
while(!Q.empty())
{
node temp=Q.top();
Q.pop();
cout << temp.idx << ' ' << temp.area << endl;
}*/
while(k--)
{
node tmp;
tmp=Q.top();
Q.pop();
while(used[tmp.left]||used[tmp.right])
{
tmp=Q.top();
Q.pop();
}
int index=tmp.idx;
printf("%d\n",index);
used[index]=true;
int left=points[index].left;
int right=points[index].right;
points[left].right=right;
points[right].left=left;
if(left>0)
{
//cout << "--- left ---" << left << endl;
points[left].area=fabs(get_area(left));
Q.push(points[left]);
}
if(right<n)
{
//cout << "--- right ---" << right << endl;
points[right].area=fabs(get_area(right));
Q.push(points[right]);
}
}
return 0;
}
心得:
其实还是一题简单的模拟题,稍微处理一下细节就好, 做这种题思路需要很清晰,需要考虑好小细节,需要全面考虑。用优先队列与计算几何中的相关内容可以让模拟加快一些