zoukankan      html  css  js  c++  java
  • 愤怒的小鸟

    这道题:
    用一个二维数组g[i][j]记录经过两个猪的抛物线还能经过那几个猪
    
    f[]全都初始化成无穷大
    f[i]=minn(f[i&(~g[j][k])+1);
    
    这个应该都知道了
    
    值得注意的是:
    1.精度0.000001
    2.有横坐标相同的猪:
        处理的时候可以把他两的a直接置为正数,
        dp就判断一下a>=0 continue;
    3.有原点和两个猪在同一条直线(过原点的直线)上的猪
        (y1/x1)-(y2/x2)<=0.000001;
        
    4.有坐标完全相同的猪(虽说题目上说没有)
        预处理的时候去重
    
    O(2^n*n*n)
    
    优化:
      一句话:既然这个状态的所有猪都要被打掉,
             为什么不现在打?
      意思就是:
           
        不用再枚举n*n条抛物线
        只要枚举其中一只猪所在的抛物线就可以了
        
        比如:
        有三只猪(x1,y1),(x2,y2),(x3,y3)
        过1,2猪的抛物线过3
        哪过2,3的抛物线也过1
        所以只需枚举一条即可
    
    然后就变成了O(2^n*n)

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #define mem(a,b) memset(a,b,sizeof(a))
      6 using namespace std;
      7 const double qqq=0.000004;
      8 const int N=(1<<18)+10;
      9  
     10 inline int minn(int a,int b)
     11 {
     12     return a<b?a:b;
     13 }
     14  
     15 inline int lowbit(int x)
     16 {
     17     return x&(-x);
     18 }
     19  
     20 inline double abss(double x)
     21 {
     22     if(x<0)
     23       return -x;
     24     return x;
     25 }
     26  
     27 int fin(int x)
     28 {
     29     int temp=lowbit(x);
     30     int k=1;
     31     while(1)
     32     {
     33         if((1<<(k-1))==temp)
     34           return k;
     35         ++k;
     36     }
     37 }
     38  
     39 struct son
     40 {
     41     double x,y;
     42 };
     43 son q[101];
     44  
     45 bool ok(son a,son b)
     46 {
     47     return a.x<b.x;
     48 }
     49  
     50 int t,n,m;
     51 double a[21][21],b[21][21];
     52 int g[21][21];
     53 int f[N];
     54 double o,p;
     55 int maxp;
     56 int now;
     57  
     58 void chu()
     59 {
     60     now=0;
     61     mem(a,0);
     62     mem(b,0);
     63     mem(g,0);
     64     mem(f,0x7f);
     65     mem(q,0);
     66     scanf("%d%d",&n,&m);
     67     for(int i=1;i<=n;i++)
     68     {
     69         scanf("%lf%lf",&o,&p);
     70         //cout<<o<<' '<<p<<endl;
     71         int flag=0;
     72         for(int j=1;j<=now;j++)
     73             if(o==q[j].x&&p==q[j].y)
     74             {
     75                 flag=1;
     76                 break;
     77             }
     78         if(flag==1)
     79           continue;
     80         q[++now].x=o;
     81         q[now].y=p;
     82     }
     83     n=now;
     84     maxp=(1<<n)-1;
     85     sort(q+1,q+1+n,ok);
     86     for(int i=1;i<=n;i++)
     87       for(int j=1;j<=n;j++)
     88       {
     89             if(i==j)
     90             {
     91                 a[i][j]=-1;
     92               continue;
     93             }
     94             double x1=q[i].x,x2=q[j].x,y1=q[i].y,y2=q[j].y;
     95             if(x1==x2)
     96             {
     97                 a[i][j]=1;
     98                 continue;
     99             }
    100             if(abss(y1/x1-y2/x2)<=qqq)
    101             {
    102                 a[i][j]=1;
    103                 b[i][j]=1;
    104                 continue;
    105             }
    106             a[i][j]=(x1*y2-x2*y1)/(x2*x2*x1-x2*x1*x1);
    107             b[i][j]=(y1/x1)-(x1*y2-x2*y1)/(x2*x2-x2*x1);
    108         }
    109      
    110     for(int i=1;i<=n;i++)
    111       for(int j=1;j<=n;j++)
    112       {
    113             if(q[i].x==q[j].x)
    114             {
    115                 g[i][j]=g[i][j]|(1<<(i-1));
    116                 g[i][j]=g[i][j]|(1<<(j-1));
    117                 continue;
    118             }
    119             if(i==j)
    120             {
    121                 g[i][j]=g[i][j]|(1<<(i-1));
    122               continue;
    123             }
    124             g[i][j]=g[i][j]|(1<<(i-1));
    125             g[i][j]=g[i][j]|(1<<(j-1));
    126             for(int k=1;k<=n;k++)
    127             {
    128                 if(k==i||k==j)
    129                     continue;
    130                 if(q[k].x==q[i].x||q[k].x==q[j].x)
    131                   continue;
    132                 if(a[i][j]>=0)
    133                   continue;
    134                 double temp=a[i][j]*q[k].x*q[k].x+b[i][j]*q[k].x;
    135                 double temp1=abss(q[k].y-temp);
    136                 if(temp1<=qqq)
    137                 {
    138                   g[i][j]=g[i][j]|(1<<(k-1));
    139                   //cout<<"a[i][j]="<<a[i][j]<<' ';
    140                   //cout<<"i="<<i<<" j="<<j<<" k="<<k<<" temp="<<temp<<" y[k]="<<q[k].y<<endl;
    141                 }
    142             }
    143         }
    144 }
    145  
    146 void work()
    147 {
    148     f[0]=0;
    149     for(int i=1;i<=maxp;i++)
    150     {
    151         int temp=fin(i);
    152         for(int j=1;j<=n;j++)
    153         {
    154             if(a[temp][j]>=0)
    155             {
    156               f[i]=minn(f[i],f[i&(~g[temp][j])]+2);
    157               continue;
    158             }
    159             f[i]=minn(f[i&(~g[temp][j])]+1,f[i]);
    160             //cout<<"i="<<i<<" f[i]="<<f[i]<<endl;
    161         }
    162     }
    163     printf("%d
    ",f[maxp]);
    164 }
    165      
    166      
    167  
    168 int main(){
    169     //freopen("2.txt","w",stdout);
    170     //freopen("angrybirds.in","r",stdin);
    171     //freopen("angrybirds.out","w",stdout);
    172     scanf("%d",&t);
    173     while(t--)
    174     {
    175         chu();
    176         work();
    177     }
    178      
    179      
    180      
    181     //while(1);
    182     return 0;
    183 }
    View Code
  • 相关阅读:
    AppScan安全问题解决方案
    WPF方法 获取控件在屏幕的位置和自动控件位置
    WPF获取鼠标点击位置和API使用
    system.windows.controls
    .net 获取项目的根目录
    InvokeRequired
    控件取图片和矩形框 小测试
    mariadb 设置远程访问
    代码生成器 链接
    分享个网站
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7248187.html
Copyright © 2011-2022 走看看