牛客競(jìng)賽題目講解_憤怒的小鳥(noip)
//??https://ac.nowcoder.com/acm/problem/16431
#include "stdafx.h"
//#include <bits/stdc++.h>
#include <algorithm>?
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#define db double
#define mindb 1e-6
using namespace std;
int t,n,m,fly[20][20],f[300000];
db a,b,x[20],y[20];
float arr[32][2]={
1.00, 5.00,
2.00, 8.00,
3.00 ,9.00,
4.00, 8.00,
5.00, 5.00
};
int main()
{?
//scanf("%d",&t);
//while (t--)
{
n=5;
//scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i)
//scanf("%lf%lf",&x[i],&y[i]);
{
x[i]=arr[i-1][0];
y[i]=arr[i-1][1];
}
/*
T={1,2,3,4,5}
21=? 10101? 表示子集? {1,3,5}
? */
// fly[i][j]表示i,j 兩個(gè)點(diǎn)確定的拋物線所能經(jīng)過哪些點(diǎn)
memset(fly,0,sizeof(fly));
for (int i=1;i<n;++i) fly[i][i]|=1<<(i-1);// 只剩下一個(gè)點(diǎn)也需要一條曲線
for (int i=1;i<n;++i)
for (int j=i+1;j<=n;++j)
{
if (fabs(x[i]-x[j])<mindb) continue;
a=(y[i]/x[i]-y[j]/x[j])/(x[i]-x[j]);
if (a>=0) continue;
b=y[i]/x[i]-x[i]*a;
for (int k=1;k<=n;++k)
if (fabs(y[k]/x[k]-(a*x[k]+b))<mindb) fly[i][j]|=1<<(k-1);//預(yù)處理fly[i][j]
}
memset(f,0X3f,sizeof(f));
f[0]=0;//初始化
// f[s]表示目前被消滅的豬的情況是s, 最少使用的鳥(曲線)的數(shù)量
for (int s=0;s<(1<<n)-1;++s)
{
//找到任意一個(gè)不在s 中的列x
? ? ? ? ? ? int x = 0;
? ? ? ? ? ? for(int i = 1; i <= n; i ++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //i點(diǎn)不在s 中的列x
? ? ? ? ? ? ? ? if((s >> (i-1) & 1) == 0)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? x = i;
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? //枚舉所有點(diǎn),計(jì)算覆蓋x點(diǎn)的新集合s| fly[x][j]的最優(yōu)解
? ? ? ? ? ? for(int i = 1; i <= n; i ++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? f[s | fly[x][i]] = min(f[s | fly[x][i]], f[s] + 1);
? ? ? ? ? ? }?
}
printf("%d\n",f[(1<<n)-1]);
}
return 0;
}