[LOJ] #2363「NOIP2016」愤怒的小鸟
精度卡了一个点,别人自带大常数,我自带大浮点误差qwq.
听了好几遍,一直没动手写一写。
f[S]表示S集合中的猪被打死的最少抛物线数,转移时考虑枚举两个点,最低位的0为第一个点,枚举第二个点,构造一条抛物线。
检查这条抛物线能否“顺便”打死更多的猪,然后转移即可。
注意存在一种情况,只剩下一个点,这时候要给最低位0单独开一条抛物线(体现在代码里就是f[i|(1<<(st-1))]单独转移一次)
//失误 这是一个 #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; typedef long double db; const int MAXN=19; const db eps=1e-9; inline void calc(db x1,db y1,db x2,db y2,db &a,db &b){ a=(db)1.0*(x1*y2-x2*y1)/(x1*x2*(x2-x1)); b=(db)1.0*(x1*x1*y2-x2*x2*y1)/(x1*x2*(x1-x2)); } inline db F(db a,db b,db x){return (db)1.0*a*x*x+1.0*b*x;} inline bool equal(db x,db y){return fabs(x-y)<=eps;} int n,useless; db px[MAXN],py[MAXN]; int f[1<<MAXN]; void solve(){ scanf("%d%d",&n,&useless); memset(f,0x7f,sizeof(f)); f[0]=0; for(int i=1;i<=n;i++) scanf("%Lf%Lf",&px[i],&py[i]); int st=0;db u,v; for(int i=0;i<(1<<n);i++){ for(st=1;st<=n;st++)if(!((1<<(st-1))&i))break; f[i|(1<<(st-1))]=min(f[i|(1<<(st-1))],f[i]+1); for(int j=st+1;j<=n;j++){ if((1<<(j-1))&i) continue; int tmp=i|(1<<(st-1)); calc(px[st],py[st],px[j],py[j],u,v); if(u>=0) continue; tmp|=(1<<(j-1)); for(int k=1;k<=n;k++){ if(k==j||k==st) continue; if(i&(1<<(k-1))) continue; if(equal(F(u,v,px[k]),py[k])) tmp|=(1<<(k-1)); } f[tmp]=min(f[tmp],f[i]+1); } } cout<<f[(1<<n)-1]<<endl; } int main(){ int T; scanf("%d",&T); while(T--) solve(); return 0; }
本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9325737.html