您的位置:首页 > 其它

uva11008 状态压缩~最优值

2013-06-07 15:09 435 查看
题目大意是给n个点,去点至少m个点,最少需要几条直线。

首先,将在一条直线上的点预处理出来,然后从0开始加状态,只要状态中1的个数>=m就作比较。

ACcode:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int NS=1<<16;
const int MS=20;

struct Point
{
int x,y;
}p[MS];

int n,m;
int dp[NS],num[NS];
int state[NS],top;

int getone(int x)
{
int cnt=0;
for (;x;cnt++,x&=x-1);
return cnt;
}

void init()
{
for (int i=0;i<NS;i++)
num[i]=getone(i);
}

void prepare()
{
top=0;
int st,x1,y1,x2,y2;
for (int i=0;i<n;i++)
for (int j=i+1;j<n;j++)
{
st=(1<<i)+(1<<j);
x1=p[j].x-p[i].x;
y1=p[j].y-p[i].y;
for (int k=j+1;k<n;k++)
{
x2=p[k].x-p[i].x;
y2=p[k].y-p[i].y;
if (x1*y2==x2*y1)
st|=(1<<k);
}
state[top++]=st;
}
x1=0;
sort(state,state+top);
for (int i=0;i<top;i++)
{
y1=1;
for (int j=i+1;j<top;j++)
if ((state[i]&state[j])==state[i])
{
y1=0;
break;
}
if (y1) state[x1++]=state[i];
}
top=x1;
}

int Min(int a1,int b1)
{
return a1<b1?a1:b1;
}

int main()
{
init();
int T,cas=0,lim,t,res;
scanf("%d",&T);
while (T--)
{
res=MS;
scanf("%d %d",&n,&m);
for (int i=0;i<n;i++)
scanf("%d %d",&p[i].x,&p[i].y);
prepare(),lim=(1<<n);
for (int i=1;i<lim;i++)
dp[i]=MS;
dp[0]=0;
for (int i=0;i<lim;i++)
{
for (int j=0;j<top;j++)
{
t=state[j];
dp[i|t]=Min(dp[i|t],dp[i]+1);
}
if (num[i]>=m) res=Min(res,dp[i]);
}
printf("Case #%d:\n%d\n",++cas,res);
if (T) printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: