洛谷P2831 愤怒的小鸟

洛谷P2831 愤怒的小鸟

原题链接

题解

首先简单数学公式送上。
\(ax_1^2+bx_1=y_1\)
\(ax_2^2+bx_2=y_2\)
\(ax_1^2x_2+bx_1x_2=y_1x_2\)
\(ax_2^2x_1+bx_2x_1=y_2x_1\)
\(a=(y_1x_2-y_2x_1)/x_1x_2(x_1-x_2)\)
\(b=(y_1-ax_1^2)/x_1\)
不用证明吧。。。

85分

状态压缩。每次枚举两个点计算抛物线,然后消除这条线上所有点,再转移。

// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
typedef long long ll;
il int gi(){
    rg int x=0,f=1;rg char ch=getchar();
    while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
#define db double
db x[18],y[18],eps=0.00000001;
int f[1<<18],n;
il int dp(int v){
    if(v==0)return 0;
    if(v==(v&-v))return 1;
    if(f[v])return f[v];
    f[v]=233;
    rep(i,0,n-1)if(v&(1<<i))rep(j,i+1,n-1)if((v&(1<<j))){
        db a=(y[i]*x[j]-y[j]*x[i])/(x[i]*x[j]*(x[i]-x[j])),b=(y[i]-a*x[i]*x[i])/(x[i]);
        if(a>=0)continue;
        int V=v;
        rep(k,0,n-1)if((V&(1<<k))&&fabs(a*x[k]*x[k]+b*x[k]-y[k])<=eps)V^=1<<k;
        f[v]=min(f[v],dp(V)+1);
    }
    rep(i,0,n-1)if(v&(1<<i))f[v]=min(f[v],dp(v^(1<<i))+1);
    return f[v];
}
il vd work(){
    n=gi();gi();
    rep(i,0,n-1)scanf("%lf%lf",&x[i],&y[i]);
    rep(i,0,(1<<n)-1)f[i]=0;
    printf("%d\n",dp((1<<n)-1));
}
int main(){
    int T=gi();
    while(T--)work();
    return 0;
}

AC算法

上面理论复杂度\(O(2^nn^2T)\)。会炸。
思考原因。
显然算重情况较多。
再想想。。。每个状态的第一头猪最后肯定要被打死(废话)。强制它第一个死,只需枚举一个点
理论复杂度\(O(2^nnT)\)

// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
typedef long long ll;
il int gi(){
    rg int x=0,f=1;rg char ch=getchar();
    while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
#define db double
db x[18],y[18],eps=0.0000001;
int f[1<<18],n;
il int dp(int v){
    if(v==0)return 0;
    if(v==(v&-v))return 1;
    if(f[v])return f[v];
    f[v]=233;
    int j=log2(v&-v);
    rep(i,j+1,n-1)if(v&(1<<i)){
        db a=(y[i]*x[j]-y[j]*x[i])/(x[i]*x[j]*(x[i]-x[j])),b=(y[i]-a*x[i]*x[i])/(x[i]);
        if(a>=0)continue;
        int V=v;
        rep(k,j,n-1)if((V&(1<<k))&&fabs(a*x[k]*x[k]+b*x[k]-y[k])<=eps)V^=1<<k;
        f[v]=min(f[v],dp(V)+1);
    }
    f[v]=min(f[v],dp(v-(v&-v))+1);
    return f[v];
}
il vd work(){
    n=gi();gi();
    rep(i,0,n-1)scanf("%lf%lf",&x[i],&y[i]);
    rep(i,0,(1<<n)-1)f[i]=0;
    printf("%d\n",dp((1<<n)-1));
}
int main(){
    int T=gi();
    while(T--)work();
    return 0;
}
posted @ 2017-08-20 20:45  菜狗xzz  阅读(167)  评论(0编辑  收藏  举报