1. 程式人生 > >「NOIP2016」 憤怒的小鳥【狀態壓縮】

「NOIP2016」 憤怒的小鳥【狀態壓縮】

par[i][j]par[i][j]表示選擇第iijj兩隻小鳥得到的a,ba,b值可以打中哪些小鳥。

然後直接注意精度轉移一下就可以了吖:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define db double
#define rep(i,x,y) for(int i=(x);i<=(y);i++)
#define repl(i,x,y) for(int i=(x);i<(y);i++)
#define repd(i,x,y) for(int i=(x);i>=(y);i--)
using namespace std;

const int N=20;
const int Inf=1e9;
const db eps=1e-10;

int t,n,m,f[1<<N],par[N][N];

struct node {
	db x,y;
}bird[N];

void init() {
	scanf("%d%d",&n,&m);m=(1<<n)-1;
	
	rep(i,1,n) scanf("%lf%lf",&bird[i].x,&bird[i].y);
	
	rep(i,1,n) rep(j,i+1,n) {
		par[i][j]=0;
		if(fabs(bird[i].x-bird[j].x)<eps) continue;
		
		db x1=bird[i].x;
		db y1=bird[i].y;
		db x2=bird[j].x;
		db y2=bird[j].y;
		
		db b=(y1*x2*x2-y2*x1*x1)/(x1*x2*(x2-x1));
		db a=(y1-b*x1)/(x1*x1);
		
		if(a<-eps) rep(k,1,n) {
			db x=bird[k].x,y=bird[k].y;
			if(fabs(a*x*x+b*x-y)<=eps) par[i][j]|=(1<<(k-1));
		}
	}
}

void solve() {
	rep(i,1,m) f[i]=Inf;f[0]=0;
	
	rep(s,0,m) if(f[s]!=Inf) {
		rep(i,1,n) {
			rep(j,i+1,n) f[s|par[i][j]]=min(f[s|par[i][j]],f[s]+1);
			f[s|(1<<(i-1))]=min(f[s|(1<<(i-1))],f[s]+1);
		}	
	} 
	
	printf("%d\n",f[m]);
}

int main() {
	scanf("%d",&t);
	
	while(t--) {
		init();
		solve();
	}

	return 0;
}