回溯 NOIP2016 愤怒的小鸟(回溯AC poi?后来发现只是这个题剪枝很有效)

来源:互联网 发布:北京人口数据统计 编辑:程序博客网 时间:2024/05/18 17:41



。。。。没什么可以多说的,就是。。。



直接用回溯可以解决的事情为什么要去写集合dp呢????(手动滑稽)


分析:

状态设计:run(n,m)准备消灭第n只猪,已经使用了m只小鸟。
每一只将要被消灭的猪有两种选择:
1、使用一只新的小鸟消灭它!
2、使用一只旧的小鸟消灭它!
好吧实际上不用算排列,想了想这完全没有必要。 
我们还有最优性剪枝!!! 

加上这个题目本身的限制又多(鸟的弹道),直接AC,快如飞飞!!(m是什么我不知道233333)

PS:注意在双精度判断大于等于0的时候是判断是否大于等于-eps!!!(一巴掌)还有一些数学推导就靠读者自己啦!(MDZZ兴奋个什么劲?!)


AC代码:

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>using namespace std;const int maxn=25;const double eps=0.000000001;int T,N,M;struct XY{ double x,y; }P[maxn];struct line{double a,b,xx,yy; }B[maxn];int use[maxn];int ans;bool vis[maxn];double calc(int i,int n){return fabs(B[i].a*P[n].x*P[n].x+B[i].b*P[n].x-P[n].y);}void run(int n,int m){if(n>N){if(m<ans) ans=m;return;}if(m>=ans) return;for(int i=1;i<=m;i++){if(use[i]<=1){double X1=B[i].xx,Y1=B[i].yy,X2=P[n].x,Y2=P[n].y;double d=X1/X2;if(fabs(X1*X2-X1*X1)<=eps) continue;B[i].a=(Y2*d-Y1)/(X1*X2-X1*X1);B[i].b=(Y1-B[i].a*X1*X1)/X1;if(B[i].a>=-eps) continue;use[i]++;run(n+1,m);use[i]--;}else if(calc(i,n)<=eps) run(n+1,m);}B[m+1].xx=P[n].x,B[m+1].yy=P[n].y;use[m+1]=1;run(n+1,m+1);use[m+1]=0;}int main(){freopen("test.in","r",stdin);freopen("test.out","w",stdout);scanf("%d",&T);while(scanf("%d",&N)==1){memset(B,0,sizeof(B));memset(P,0,sizeof(P));memset(use,0,sizeof(use));scanf("%d",&M);for(int i=1;i<=N;i++)scanf("%lf%lf",&P[i].x,&P[i].y);ans=25;run(1,0);printf("%d\n",ans);}return 0;}

 
原创粉丝点击