zoj 3511 Cake Robbery

 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4376

Cake Robbery

 

Time Limit: 2 Seconds      Memory Limit: 65536 KB

 

As usual, Alice finishes her delicious cake at noon. Unfortunately, the smell of cake beckoned hungry Bob, and he decided to rob one piece of cake.

The cake is a convex polygon with N edges. At the beginning, Bob cut it along the diagonals. After M cuts, Bob decided to rob the 'largest' piece of cake. Strangely, in Bob's opinion, the piece has the most number of edge is the biggest one.

Please help Bob to find the 'largest' piece.

Input

There are multiple test cases (about 20).

The first line of each test case contains two integer number N, M (5 <= N <= 10000), indicating the number of point of the cake and the cut, respectively.

The following M lines contain two integer x, y (1 <= x, y <= N), denoting the index of the starting and ending cut point. (the index of points mark from 1 to N clockwise.)

The input will guarantee that all of the cuts will not intersect inside the cake, but they may cross each other at the edge of cake, and Bob won't cut along the initial edge of the cake.

Output

Output the maximal size (most number of edges) of the piece which Bob will get.

Sample Input
7 2
3 6
7 2
Sample Output
4

 

一直没去写这题,今天心情不错,就写了下。

题意:一个N凸边形,顺时针标号从1到N,现在沿着对角线切m刀,两刀之间不相交。问你切m到后得到的凸多边形中边数最大的多边形有多少条边。

分析:因为两刀之间互不相交,所以对于每刀切出来的两个多边形存起来,按多边形的边数排序,从小到大扫描这m刀,因为是排过序的,所以当前的这刀切出来的较小的多边形对以后的切割是木有影响的,所以可以丢弃,并更新答案。因为每次都能去掉至少一个点所以复杂度为O(N)。

代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 10050
#define min(a,b) (((a)<(b))?(a):(b))
struct node
{
	int l,r,dis;
}a[N];
int next[N];
bool cmp(node a,node b)
{
	return a.dis<b.dis;
}
int main()
{
	int n,m,i,l,r,x,y,t;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		for(i=0;i<m;i++)
		{
			scanf("%d%d",&a[i].l,&a[i].r);
			if(a[i].l>a[i].r) 
				t=a[i].l,a[i].l=a[i].r,a[i].r=t;
			a[i].dis=min(a[i].r-a[i].l,n-a[i].r+a[i].l);
		}
		sort(a,a+m,cmp);
		for(i=1;i<n;i++) //next 数组记录当前顶点的后面的那个点
			next[i]=i+1;
		next[n]=1;
		int ans=0,sum=0;
		for(i=0;i<m;i++)
		{
			l=a[i].l;r=a[i].r;
			if(a[i].dis==r-l)
				x=l,y=r;
			else
				x=r,y=l;
			int tempx=x;
			int num=0;
			while(x!=y)
			{
				num++;
				x=next[x];
			}
			sum+=num-1;
			if(num+1>ans)
				ans=num+1;
			next[tempx]=y;  //更新next
		}
		if(ans<n-sum)
			ans=n-sum;
		printf("%d\n",ans);
	}
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值