【题解】洛谷P2831 愤怒的小鸟[NOIP2016] 状压DP

题目链接
dp[i]表示i状态时所需要的最少的小鸟数,state[i]表示第i条抛物线所打掉的小猪状态,
dp[i|state[j]]=min(dp[i|state[j]],dp[i]+1)

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define eps 1e-6
int n,m;
const int N=18;
int dp[1<<N];//dp[i]表示i状态时所需最少小鸟数 
double x[N],y[N];
int state[510];//记录每条抛物线 
int cnt; 
int main()
{
    //freopen("in.txt","r",stdin);
    int t;
    double a,b;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        cnt=0;
        memset(dp,0x3f,sizeof(dp));
        dp[0]=0;
        for(int i=0;i<n;i++)
        scanf("%lf%lf",&x[i],&y[i]);
        for(int i=0;i<n;i++)
        {
            state[cnt++]=(1<<i);
            for(int j=i+1,k=0;j<n;j++)
            {
                if((k>>j)&1)continue;
                a=(y[j]*x[i]-y[i]*x[j])/(x[i]*x[j]*(x[j]-x[i]));
                b=(y[i]*x[j]*x[j]-y[j]*x[i]*x[i])/(x[i]*x[j]*(x[j]-x[i]));
                if(a>=-eps)continue;
                state[cnt]=(1<<i);
                for(int o=j;o<n;o++)
                if(fabs(a*x[o]*x[o]+b*x[o]-y[o])<=eps)
                {
                    k|=(1<<o);
                    state[cnt]|=(1<<o);
                }
                cnt++;
            }
        }
        for(int i=0;i<(1<<n);i++)
        for(int j=0;j<cnt;j++)
        dp[i|state[j]]=min(dp[i|state[j]],dp[i]+1);
        printf("%d\n",dp[(1<<n)-1]);
    }
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_41958841/article/details/81637351
今日推荐