其他分享
首页 > 其他分享> > 洛谷P2831 愤怒的小鸟

洛谷P2831 愤怒的小鸟

作者:互联网

题目

状压DP。

直接枚举二进制数表示当前猪有没有被消灭的状态。

最终答案的几条抛物线必定至少撞到一个猪。而且两头猪确定一条抛物线,可以枚举两头猪,分别求出他们的抛物线所消灭猪的状态,然后可以用类似背包的方法转移DP。

有方程:
\(dp[i|(\)当前抛物线的状态\()] = min(dp[i|(\)当前抛物线的状态\()],dp[i]+1)\)

有转移:

枚举每个状态,每个状态再枚举每个可以撞到的一头猪,再用该猪枚举是否存在既能撞到该猪,又能撞到另一头猪的抛物线,然后即可确定抛物线,也可确定状态了。

#include <bits/stdc++.h>
#define N 1001001
using namespace std;
int T, n, m;
double x[1001], y[1001];
int vis[1001000], dp[1010011], ha[1001][1001];
double F(double a, double b, double x)
{
    double y = a * x * x + b * x;
    return y;
}
inline void add(int i, int j)//确定好所有抛物线的状态 
{
    if (abs(x[i] - x[j]) <= 0.0000001) return;//判断是否两个点重合 
    double b = (x[i] * x[i] * y[j] - x[j] * x[j] * y[i]) / (x[i] * x[i] * x[j] - x[j] * x[j] * x[i]);
    double a = (y[i] - b * x[i]) / (x[i] * x[i]);//两点确定一条抛物线。
    if (a < 0)//a必须小于0
    {
            ha[i][j] = (1 << i - 1) | (1 << j - 1); 
            for (int k = 1; k <= n; k++)
            if (abs(F(a, b, x[k]) - y[k]) <= 0.0000001 && k != i && k != j)
                ha[i][j] |= (1 << k - 1);//表示状态+=(1<<k-1) 用二进制表示状态。 
    }
        
}
inline void clear()
{
    memset(dp, 0x3f, sizeof(dp));
    memset(vis, 0, sizeof(vis));
    memset(ha, 0, sizeof(ha));
    dp[0] = 0;
}
int main()
{
    scanf("%d", &T);
    while (T--)
    {
        clear();
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++)
            scanf("%lf%lf", &x[i], &y[i]);//考虑搜索
        for (int i = 1; i <= n; i++)
            for (int j = i + 1; j <= n; j++)
                add(i, j);//求出i,j确定的抛物线状态 
        for (int i = 0; i < (1 << n); i++)//当前状态是i 
            for (int j = 1; j <= n; j++)//给当前状态加上一条抛物线,首先必定会撞到1个点, 
            {
                dp[i | (1 << j - 1) ] = min(dp[i | (1 << j - 1)], dp[i] + 1);
                for (int k = j + 1; k <= n; k++)//再找一个能跟j在同一条抛物线上的点,然后加上此抛物线所确定的状态。 
                    if (ha[j][k])
                        dp[i | ha[j][k]] = min(dp[i | ha[j][k]], dp[i] + 1);
            }
        printf("%d\n", dp[(1 << n)- 1]);//所有数都选上的最小代价。
    }
    return 0;
}

标签:洛谷,int,double,P2831,小鸟,枚举,抛物线,1001,dp
来源: https://www.cnblogs.com/liuwenyao/p/11800766.html