码迷,mamicode.com
首页 > 其他好文 > 详细

【NOIP2016】愤怒的小鸟

时间:2017-10-15 22:40:22      阅读:248      评论:0      收藏:0      [点我收藏+]

标签:sharp   scan   pac   logs   tin   ons   register   i+1   big   

技术分享

 

题目链接:uoj.ac/problem/265

一看到n<=18,其实就知道这是一道状压dp.

然后,我们就定义两个数组f[i][j]和dp[i].

f[i][j]表示以(0,0)(xi,yi)和(xj,yj)构成的抛物线最多可以射到几只猪的状态压成一个数,

1表示在抛物线上,0则反之,

那么先O(n3)暴力枚举一下就好了.

dp[i]表示完成状态为i的最优步数.

则dp[s|f[i][j]]=min(dp[s|f[i][j]],dp[s]+1).

O(2n)枚举状态s,

O(n2)进行状态转移,

所以总复杂度为O(2n*n2).

 

#include<iostream>
#include<cstdio>
#define BIG 1<<19
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
using namespace std;
int n,m;
int T;
const double mimi=1e-10;
double x[21],y[21];
int f[21][21];
int dp[BIG];
inline double fabs(double a){
	return a>=0?a:-a;
}
inline void deal(){
	double a,b;
	FOR(i,0,n-1)
		FOR(j,0,n-1)
			f[i][j]=0; 
	FOR(i,0,n-1)
		f[i][i]=1<<i;
	FOR(i,0,n-1)
		FOR(j,i+1,n-1){
			a=(x[i]*y[j]-x[j]*y[i])/(x[i]*x[j]*(x[j]-x[i]));
			b=(y[j]*x[i]*x[i]-y[i]*x[j]*x[j])/((x[i]-x[j])*x[i]*x[j]);
			if(a>=-mimi)
				continue;
			FOR(k,0,n-1)
				if(fabs(a*x[k]*x[k]+b*x[k]-y[k])<=mimi)
					f[i][j]|=(1<<k);
		}
}
inline void solve(){
	FOR(i,1,(1<<n))
		dp[i]=2333;
	FOR(s,0,(1<<n)-2)
		FOR(i,0,n-1)
			FOR(j,i,n-1)
				dp[s|f[i][j]]=min(dp[s|f[i][j]],dp[s]+1);
	cout<<dp[(1<<n)-1]<<endl;
	return;
}
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&m);
		FOR(i,0,n-1)
			scanf("%lf%lf",&x[i],&y[i]);
		deal();
		solve();
	}
	return 0;
}

  

【NOIP2016】愤怒的小鸟

标签:sharp   scan   pac   logs   tin   ons   register   i+1   big   

原文地址:http://www.cnblogs.com/Stump/p/7674279.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!