【NOIP2016提高组Day 2】愤怒的小鸟

Description

在这里插入图片描述

Input

在这里插入图片描述

Output

在这里插入图片描述

solution

这道题可以用状压DP来做,首先,我们先预处理出任意两个点所推出的抛物线,在找出这个抛物线所经过的点数,用一个二进制数来表示,例如经过i,j两点的抛物线经过了1,5,8点,就是g[i][j]=10001001。
然后再设f[i]为状态为i时所需要的最少抛物线的数量。此时可推出方程式f[i|g[j][l]]=min(f[i]+1,f[i|g[j][l]]),此时要注意,我们还要判断一下,可能有些点需要一个点用一条抛物线,所以在此从1枚举到n,就是f[i|(1<<j-1)]=min(f[i|(1<<j-1)],f[i]+1)。

code

#include<bits/stdc++.h>
#define rg register int
#define con continue
using namespace std;
int T,n,m,g[20][20],f[1000005];
double x[20],y[20],a,b,t;
bool pd(double x,double y){
    return abs(x-y)<(1e-6); 
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		for(rg i=1;i<=n;i++) scanf("%lf%lf",&x[i],&y[i]);
		for(rg i=1;i<=n;i++) for(rg j=i+1;j<=n;j++) g[i][j]=0;
		for(rg i=1;i<=n;i++)
		{
			for(rg j=i+1;j<=n;j++)
			{
				t=a=b=0;
				if(x[i]==x[j]) con;
				a=(y[j]/x[j]-y[i]/x[i])*1.0/(x[j]-x[i])*1.0;
				if(a>=0) con;//a要是负数
				b=y[i]/x[i]*1.0-a*x[i]*1.0;
				//确定一条抛物线,y=axx+bx
				for(rg l=1;l<=n;l++)
					if(pd(y[l]/x[l],a*x[l]+b)) t+=(1<<(l-1));
				g[i][j]=t;
			}
		}
		//把所有可能的抛物线求出来
		for(rg i=1;i<=(1<<n);i++) f[i]=99999;
		f[0]=0;
		for(rg i=0;i<(1<<n);i++)
		{
			for(rg j=1;j<=n;j++)
			{
				if(!(i&(1<<(j-1))))
				{
					for(rg l=j+1;l<=n;l++)
					{
						f[i|g[j][l]]=min(f[i|g[j][l]],f[i]+1);
					}
					f[i|(1<<j-1)]=min(f[i|(1<<j-1)],f[i]+1);
				}
			}
		}
		//枚举所有抛物线的可能
		printf("%d\n",f[(1<<n)-1]);
	}
	return 0;
}
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值