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

P2831 愤怒的小鸟

时间:2018-10-21 13:34:13      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:tps   getc   using   style   can   注意   枚举   mes   --   

传送门

看到数据范围就知道是搜索或状压DP

算了一波复杂度搜索好像过不了极限数据

搞状压

设 f [ i ] 表示所有猪的状态为 i (二进制下1表示死了,0表示没死)时需要的最少发射次数

设 p [ i ] [ j ] 存经过第 i 只猪和第 j 只猪的抛物线经过的猪的状态(可以$n^2$预处理出来,解方程都会吧..)

找到第一个没死的猪 i ,然后枚举所有其他没死的猪 j ,进行转移:

f [ i|p [ i ] [ j ] ] = min ( f [ i|p [ i ] [ j ] ],f [ i ] + 1 )

不用 n^2 枚举所有两只猪的 p [ i ] [ j ] ,因为第一头猪现在不死以后也要死,所以没有任何区别

当然还要考虑只经过一头猪的情况: f [ i|(1<<i-1) ] = min ( f[ i|(1<<i-1) ],f [ i ] +1 )

注意抛物线解析式中 a<0,记得判一下合法性

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<0||ch>9) { if(ch==-) f=-1; ch=getchar(); }
    while(ch>=0&&ch<=9) { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const double eps=1e-8;
const int N=300007;

int n,m,T;
struct data
{
    double x,y;
}d[27];
double a,b;
inline void slove(double x1,double y1,double x2,double y2)//解方程
{
    double t=x2*x2/x1/x1;
    b=(y2-y1*t)/(x2-x1*t); a=(y1-x1*b)/x1/x1;
}
int p[27][27];
int f[N];
void pre()
{
    memset(p,0,sizeof(p));
    memset(f,0x3f,sizeof(f)); f[0]=0;//记得初始化
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        {
            if(fabs(d[i].x-d[j].x)<eps) continue;//如果横坐标相同则无解
            slove(d[i].x,d[i].y,d[j].x,d[j].y);
            if(a>=0) continue;//判断合法性
            for(int k=1;k<=n;k++) if(fabs(a*d[k].x*d[k].x+b*d[k].x-d[k].y)<=eps)/*如果抛物线经过猪k就记录一下*/ p[i][j]|=(1<<k-1);
        }
}
int main()
{
    T=read();
    while(T--)
    {
        n=read(); m=read();
        for(int i=1;i<=n;i++) scanf("%lf%lf",&d[i].x,&d[i].y);
        pre(); int mx=(1<<n)-1,pos;
        for(int i=0;i<=mx;i++)
        {
            for(int j=0;j<n;j++) if( !((i>>j)&1) ) { pos=j; break; }//找到第一只没死的猪
            f[i|(1<<pos)]=min(f[i|(1<<pos)],f[i]+1);//单独考虑
            for(int j=pos+1;j<n;j++)//与其他猪一起考虑
                if( !((i>>j)&1) ) f[i|p[pos+1][j+1]]=min(f[i|p[pos+1][j+1]],f[i]+1);//注意p的下标
        }
        printf("%d\n",f[mx]);
    }
    return 0;
}

 

 

P2831 愤怒的小鸟

标签:tps   getc   using   style   can   注意   枚举   mes   --   

原文地址:https://www.cnblogs.com/LLTYYC/p/9824696.html

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