P14988 多边形 个人题解

题目链接

题目大意

给定 \(n\) 根木棍,问从这些木棍中选取 \(k\)\(3\le k \le n\))根木棍,能否拼凑出一个面积不为 \(0\)\(k\) 边形。

Solution

大家在初中甚至小学的时候就应该学到过三角形的三边关系,那就是两边之和大于最长的第三边,同理对于这道题的 \(k\) 边形也适用,原因就是当 \(k-1\) 边之和等于最长的第 \(k\) 边时,这个 \(k\) 边形刚好是一条直线,所以只要这 \(k-1\) 边之和大于最长的第 \(k\) 边,这个 \(k\) 边形的面积就一定不为 \(0\)

那么我们可以将这 \(n\) 根木棍从小到大排序,依次从这些木棍中选出相邻的 \(k\) 根木棍,判断最长那根的长度是否比其他的木棍长度和小,如果是直接退出循环就好了。为什么要取相邻的木棍呢?因为相邻的木棍之间的长度差一定是最小的,那么补足这些长度差所需要的木棍长度就是最少的,能构成 \(k\) 边形的几率就是最大的。然后由于我们不能每一次都去算这 \(k-1\) 根木棍的和,所以我们在排完序之后做一个前缀和,这样就能快速求出这 \(k-1\) 根木棍的和,然后去与第 \(k\) 根木棍长度作比较。

代码

#include<bits/stdc++.h>
#define int long long//不开long long见祖宗 
using namespace std;
const int N=2e5+6;
inline 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*10+c-'0';
		c=getchar();
	}
	return x*f;
}
int n=read(),a[N],s[N];
signed main(){
	for(int i=1;i<=n;i++)
		a[i]=read();
	sort(a+1,a+n+1);//从小到大排序 
	for(int i=1;i<=n;i++)//做一遍前缀和 
		s[i]=s[i-1]+a[i];
	for(int k=3;k<=n;k++){//枚举构成的k边形 
		bool ok=false;
		for(int l=1,r=k;r<=n && !ok;l++,r++){
			int x=s[r-1]-s[l-1];//k-1根木棍的和 
			if(x>a[r]) ok=true;//如果满足和大于最长边的长度,直接记录跳出循环 
		}
		if(ok) printf("%lld ",k);
	}
	return 0;
}
posted @ 2026-01-18 17:49  See_you_soon  阅读(1)  评论(0)    收藏  举报