hdu 1966 Minimax Triangulation

咱其实最讨厌图论了 =.=  写这道题简直蛋疼。

给予一个多边形,对其进行三角分割后最大的那个三角形的面积最小值为多少。

像这种肯定是<贪心、DP、搜索>中的一种,贪心么没什么直观的规律用不了,搜索的话虽然多边形的点少(3<=n<=50)但是时间复杂度肯定过不去,后来也想了一下,用记忆化搜索,不过中间状态想不出好方法记录,所以最后想想还是用DP了。

嘛,用DP的时候直接就想成dp[L][R]代表从第L个顶点到第R个顶点的最优分割值,这样的话递推公式也出来了dp[L][R]=min{   max(  dp[L][Mid]  , dp[Mid][R]  , Δ(L,Mid,R) )   ,    L <  Mid < R  }(相当于把多边形分割为多边形L~Mid,多边形Mid~R,和一个三角形(L,Mid,R)这样三块)。

考虑到这样分割后都是连续点连成的多边形,可能会漏掉那些非连续的情况。但是后来想了想,连续的情况是可以组成那些非连续的情况的。那就不用加以处理。

恩,这样应该是没问题了,然后交了一发,WA。又不停的改细节,交了5发,全WA。卧槽怎么可能?(╯‵□′)╯︵┻━┻(掀桌)

然后看了下题目的测试例子,可能会出现凹多边形(笑)。

好吧,那就改,怎么改呢。就是排除掉那些违规分割。例如这种:

这种Δ(L,Mid,R) 就是违规分割的,因为其中还包含了其他另外的顶点。那问题就在于判断是否有顶点处于三角形之中,这个用叉积也可以判断就不说了。

我只想说,代码写的简直难看。



#include <stdio.h>
#include <algorithm>
using namespace std;

const int MAXM = 61;
const int INF = 0x3f3f3f3f;

int dp[MAXM][MAXM];

int Num;
int Clock;

int X[MAXM];
int Y[MAXM];

int Calcu(int a,int b,int c)
{
	int x1=X[b]-X[a];
	int x2=X[c]-X[a];
	int y1=Y[b]-Y[a];
	int y2=Y[c]-Y[a];
	return Clock*(x1*y2-y1*x2);
}

void Judge()
{
	int sum=0;
	Clock=1;
	for(int i=2;i<Num;i++)
	{
		sum+=Calcu(1,i,i+1);
	}
	if(sum<0)Clock=-1;
}

void Read_Case()
{
	scanf("%d",&Num);
	for(int i=1;i<=Num;i++)
	{
		scanf("%d %d",X+i,Y+i);
	}
}

bool Edge(int a,int b,int c)
{
	int i;
	int ans=abs((int)Calcu(a,b,c));
	for(i=1;i<=Num;i++)
	{
		if(i==a||i==b||i==c)continue;
		if(ans==abs((int)Calcu(i,b,c))+abs((int)Calcu(i,b,a))+abs((int)Calcu(i,a,c)))break;
	}
	if(i>Num)return 0;
	return 1;
}

void Deal()
{
	for(int i=1;i<=Num;i++)dp[i][i]=0;
	for(int i=1;i<Num;i++)dp[i][i+1]=0;
	for(int i=1;i<=Num-2;i++)
	{
		dp[i][i+2]=Calcu(i,i+1,i+2);
	}
	int R,L,Mid,Limit,Ans;
	for(int dis=3;dis<Num;dis++)
	{
		Limit=Num-dis;
		for(L=1;L<=Limit;L++)
		{
			R=L+dis;
			dp[L][R]=INF;
			for(Mid=L;Mid<=R;Mid++)
			{
				if(Edge(L,Mid,R))continue;
				Ans=max(Calcu(L,Mid,R),max(dp[L][Mid],dp[Mid][R]));
				dp[L][R]=min(dp[L][R],Ans);
			}
		}
	}
	printf("%.1lf\n",dp[1][Num]/2.0);
}

int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		Read_Case();
		Judge();
		Deal();
	}
}


要死要死   什么东西扯个图上来就想老半天 = =


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值