11008 - Antimatter Ray Clearcutting

/*
自己沒思路,去網上看了大牛的題解纔會的,竟然是2進制狀態壓縮啊,感覺也不難就是自己
想不出來,之前還有一題是10911 - Forming Quiz Teams 也是2進制狀態壓縮,像這種
數據量不大於30,狀態轉移和每個元素都可能有關係的DP應該都是用狀態壓縮吧。
DP每次最關鍵的是找兩棵沒被砍的樹然後找到這兩棵樹所在直線的所有沒被砍的樹,然後砍掉進入下一狀態。 
*/
#include <stdio.h>
#include <string.h>
#define maxn (1<<17)
#define N 20
int n,m,d[maxn],x[N],y[N];
int isline(int i,int j,int k)
{
	int a=x[i]-x[j],b=y[i]-y[j];
	int c=x[i]-x[k],d=y[i]-y[k];
	return a*d==b*c;
}
int min(int a,int b)
{
	if(a<b) return a;
	else return b;
}
int dp(int ct,int cu)
{
	if(d[ct]<(1<<30)) return d[ct];
	if(cu<=0) return d[ct]=0;
	if(cu==1) return d[ct]=1;
	for(int i=0;i<n;i++)
	{
		if((1<<i)&ct)
		for(int j=i+1;j<n;j++)
		if((1<<j)&ct)
		{
			int t=ct,co=0;
			for(int k=0;k<n;k++)
			if((1<<k)&t&&isline(i+1,j+1,k+1))
			{t-=(1<<k);co++;}
			d[ct]=min(d[ct],dp(t,cu-co)+1);
		}
	}
	return d[ct];
}
int main()
{
	int t;
	scanf("%d",&t);
	for(int tt=1;tt<=t;tt++)
	{
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
		scanf("%d%d",&x[i],&y[i]);
		memset(d,0x7f,sizeof(d));
		printf("Case #%d:\n",tt);
		printf("%d\n",dp((1<<n)-1,m));
		if(t!=tt) printf("\n");
	}
	return 0;
}

發佈了22 篇原創文章 · 獲贊 2 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章