LG2831 愤怒的小鸟

题意

分析

看n的范围只有18,考虑状压dp。

\(f(s)\)表示过集合s中的点所需最小的抛物线数量。

然后枚举点对算抛物线,判断其他点是否在抛物线上来转移。

细节

判断能否构成抛物线只需要判断斜率关系,具体来说是

\[\frac{y_i}{x_i} > \frac{y_j-y_i}{x_j-x_i} \]

判断三点是否在同一抛物线上,考虑方程

\[\left\{ \begin{array}{} a x_i^2 + bx_i & = & y_i \\ a x_j^2 + bx_j & = & y_j \\ a x_k^2 + bx_k & = & y_k \\ \end{array} \right. \]

有解的条件是矩阵

\[\left[ \begin{matrix} x_i^2 & x_i & y_i \\ x_j^2 & x_j & y_j \\ x_k^2 & x_k & y_k \end{matrix} \right] \]

线性相关,只需行列式为0。(B君太优秀了。)

代码

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#define rg register
#define il inline
#define co const
#pragma GCC optimize ("O0")
using namespace std;
template<class T> il T read(rg T&x)
{
    rg T data=0;
	rg int w=1;
    rg char ch=getchar();
    while(!isdigit(ch))
    {
		if(ch=='-')
			w=-1;
		ch=getchar();
	}
    while(isdigit(ch))
        data=10*data+ch-'0',ch=getchar();
    return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff;

const int MAXN=20;
int n,m,ms;
ll x[MAXN],y[MAXN];

int f[1<<MAXN|7];

il void update(rg co int&x)
{
	for(rg int i=0;i<=ms;++i)
	{
		f[i|x]=min(f[i|x],f[i]+1);
//		cerr<<(i|x)<<" f="<<f[i|x]<<" fi+1="<<f[i]+1<<" min="<<min(f[i|x],f[i]+1)<<endl;
	}
		
}

il bool in(rg co int&i,rg co int&j,rg co int&k)
{
	rg ll det=0;
	det += x[i] * x[i] * x[j] * y[k];
	det += x[i] * y[j] * x[k] * x[k];
	det += y[i] * x[j] * x[j] * x[k];
	det -= y[i] * x[j] * x[k] * x[k];
	det -= x[i] * x[j] * x[j] * y[k];
	det -= x[i] * x[i] * y[j] * x[k];
	return det==0;
}

int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
	rg int T;
	read(T);
	while(T--)
	{
		memset(f,0x3f,sizeof f);
		f[0]=0; // edit 1:the init of f
		
		read(n);read(m);
		ms=(1<<n)-1;
		for(rg int i=0;i<n;++i)
		{
			rg double xi,yi;
			scanf("%lf %lf",&xi,&yi);
			x[i] = ll(100 * xi + 0.5);
			y[i] = ll(100 * yi + 0.5);
//			cerr<<i<<" x="<<x[i]<<" y="<<y[i]<<endl;
		}
		
		for(rg int i=0;i<n;++i)
		{
			update(1<<i);
			for(rg int j=0;j<n;++j)
				if(x[j] > x[i] && y[i] * (x[j] - x[i]) > x[i] * (y[j] - y[i]))
				{
					rg int s=(1<<i)|(1<<j);
					for(rg int k=0;k<n;++k)
						if(in(i,j,k))
							s|=(1<<k);
//					cerr<<i<<" "<<j<<" s="<<s<<endl;
					update(s);
				}
		}
		
/*		for(int i=0;i<1<<n;++i)
			cerr<<i<<" f="<<f[i]<<endl;*/
		
		printf("%d\n",f[ms]);
	}
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

posted on 2018-10-17 20:04  autoint  阅读(154)  评论(0编辑  收藏  举报

导航