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;
}

你可能感兴趣的:(11008 - Antimatter Ray Clearcutting)