题面:
二维平面上有N个点,有一把刷子,刷一次可以把一条直线上的所有点都刷掉。问最少刷多少次,可以把全部的点都刷完。
hack 数据:
6
1 1
1 1
41 -9
83 -73
-1 69
-29 -81
无输出,应该是死循环了,求调。
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
int x[20], y[20];
int dp[1<<16], line[20][20];
int same[20],same2[20];
int n;
inline int check(int i,int j,int k)
{
int y2=y[j];
int y1=y[i];
int y3=y[k];
int x2=x[j];
int x1=x[i];
int x3=x[k];
if(y3*(x2-x1)==(y2-y1)*x3+x2*y1-x1*y2) return 1;
else return 0;
}
void pre(int n)
{
for(int i=0;i<n;i++)
{
line[i][i]=(1<<i);
for(int j=i+1;j<n;j++)
{
if(x[i]==x[j] and y[i]==y[j]) continue;
for(int k=0;k<n;k++)
{
if(check(i,j,k)) line[i][j]|=(1<<k);
}
}
}
}
int dfs(int status)
{
if(status == (1 << n) - 1)
{
return 0;
}
if(dp[status]!=0x3f3f3f3f) return dp[status];
for(int i= 0;i<n; i++)
{
if(!(status&(1<<i)))
{
for (int j =i+1;j<n; j++)
{
int mask = status|line[i][j];
//cout<<mask<<endl;
dp[status] = min(dp[status], dfs(mask) + 1);
// cout<<dp[status]<<endl;
}
}
//cout<<dp[status]<<endl;
}
return dp[status];
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
cin>>n;
memset(line,0,sizeof(line));
memset(dp,0x3f3f3f3f,sizeof(dp));
dp[(1<<n)-1]=0;
for(int i=0;i<n;i++)
{
scanf("%d%d",&x[i],&y[i]);
}
if(n==1)
{
cout<<1<<endl;
}
else
{
pre(n);
// cout<<(1<<3)<<endl;
// 1000
cout<<dfs(0)<<endl;
}
}
return 0;
}