1. 程式人生 > 實用技巧 >【洛谷P2831】憤怒的小鳥

【洛谷P2831】憤怒的小鳥

題目

題目連結:https://www.luogu.com.cn/problem/P2831

Kiana 最近沉迷於一款神奇的遊戲無法自拔。

簡單來說,這款遊戲是在一個平面上進行的。

有一架彈弓位於 \((0,0)\) 處,每次 Kiana 可以用它向第一象限發射一隻紅色的小鳥,小鳥們的飛行軌跡均為形如 \(y=ax^2+bx\) 的曲線,其中 \(a,b\) 是 Kiana 指定的引數,且必須滿足 \(a < 0\)\(a,b\) 都是實數。

當小鳥落回地面(即 \(x\) 軸)時,它就會瞬間消失。

在遊戲的某個關卡里,平面的第一象限中有 \(n\) 只綠色的小豬,其中第 \(i\) 只小豬所在的座標為 \(\left(x_i,y_i \right)\)

如果某隻小鳥的飛行軌跡經過了 \(\left( x_i, y_i \right)\),那麼第 \(i\) 只小豬就會被消滅掉,同時小鳥將會沿著原先的軌跡繼續飛行;

如果一隻小鳥的飛行軌跡沒有經過 \(\left( x_i, y_i \right)\),那麼這隻小鳥飛行的全過程就不會對第 \(i\) 只小豬產生任何影響。

例如,若兩隻小豬分別位於 \((1,3)\)\((3,3)\),Kiana 可以選擇發射一隻飛行軌跡為 \(y=-x^2+4x\) 的小鳥,這樣兩隻小豬就會被這隻小鳥一起消滅。

而這個遊戲的目的,就是通過發射小鳥消滅所有的小豬。

這款神奇遊戲的每個關卡對 Kiana 來說都很難,所以 Kiana 還輸入了一些神祕的指令,使得自己能更輕鬆地完成這個遊戲。這些指令將在【輸入格式】中詳述。

假設這款遊戲一共有 \(T\) 個關卡,現在 Kiana 想知道,對於每一個關卡,至少需要發射多少隻小鳥才能消滅所有的小豬。由於她不會算,所以希望由你告訴她。

思路

顯然設 \(f[s]\) 表示已經打掉的豬的集合為 \(s\) 所需的步數。
預處理出 \(S[i][j]\) 表示 豬 \(i,j\) 座標以及 \((0,0)\) 所構成的拋物線能打到的豬的集合。轉移時列舉兩個豬轉移即可。
時間複雜度 \(O(n^22^n)\)

程式碼

#include <bits/stdc++.h>
#define reg register
using namespace std;

const int N=20,M=(1<<18)+10;
const double eps=1e-8;
int Q,n,ans,type,S[N][N],f[M],cnt[M];
double X[N],Y[N];

void prework()
{
	memset(f,0x3f3f3f3f,sizeof(f));
	memset(S,0,sizeof(S));
	f[0]=0; ans=114514;
}

int main()
{
	cnt[0]=0;
	for (reg int i=1;i<M;i++)
		cnt[i]=cnt[i-(i&-i)]+1;
	scanf("%d",&Q);
	while (Q--)
	{
		prework();
		scanf("%d%d",&n,&type);
		for (reg int i=1;i<=n;i++)
			scanf("%lf%lf",&X[i],&Y[i]);
		for (reg int i=1;i<=n;i++)
			for (reg int j=1;j<=n;j++)
			{
				double rate=X[j]/X[i];
				double a=(rate*Y[i]-Y[j])/(rate*X[i]*X[i]-X[j]*X[j]);
				double b=(Y[i]-a*X[i]*X[i])/X[i];
				if (a>=0 || X[i]==X[j]) continue;
				for (reg int k=1;k<=n;k++)
					if (fabs(Y[k]-a*X[k]*X[k]-b*X[k])<=eps) S[i][j]|=(1<<k-1);
			}
		int Maxn=(1<<n);
		for (reg int s=0;s<Maxn;s++)
			for (reg int i=1;i<=n;i++)
				for (reg int j=1;j<=n;j++)
					if (S[i][j]) f[s|S[i][j]]=min(f[s|S[i][j]],f[s]+1);
		for (reg int i=0;i<Maxn;i++)
			ans=min(ans,f[i]+n-cnt[i]);
		printf("%d\n",ans);
	}
	return 0;
}