Light OJ 1018 - Brush (IV)

时间:2023-03-10 06:27:45
Light OJ   1018 - Brush (IV)

题目大意:

    一个二维平面上有N个点,一把刷子,刷一次可以把一条线上的所有点都刷掉。问最少刷多少次,可以把全部的点都刷完
状态压缩DP, 用记忆化搜索来写, 需要有个优化不然会超时。
========================================================================================
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;
#define Max(a,b) (a>b?a:b)
const int INF = 1e9+;
const int maxn = ;
const int MOD = ;
int Line[maxn][maxn];
int dp[], n;
struct node
{
int x, y;
} P[maxn]; int DFS(int sta)
{
if(dp[sta] != - )
return dp[sta];
dp[sta] = INF;
int cnt = ;
for(int i=; i<n; i++)
if( (sta&(<<i)) ) cnt ++; if(cnt == )
return dp[sta] = ;
else if(cnt <= )
return dp[sta] = ; for(int a=; a<n; a++)
{
if( (sta&(<<a)) )
{
for(int b=a+; b<n; b++)
{
if((sta&(<<a)) == ) continue;
int newSta = (sta|Line[a][b]) - Line[a][b];
dp[sta] = min(dp[sta], DFS(newSta) + );
}
break;///此处是优化
}
}
return dp[sta];
} int main()
{
int T, Lim, cas = ;
scanf("%d", &T);
while(T --)
{
memset(dp, -, sizeof(dp));
memset(Line, , sizeof(Line));
scanf("%d",&n);
for(int i=; i<n; i++)
scanf("%d %d", &P[i].x, &P[i].y); for(int i=; i<n; i++)
{
Line[i][i] = (<<i);
for(int j=i+; j<n; j++)
{
for(int k=; k<n; k++)
{
if( (P[i].y-P[j].y)*(P[i].x-P[k].x) == (P[i].y-P[k].y)*(P[i].x-P[j].x) )
Line[i][j] += (<<k);
}
Line[j][i] = Line[i][j];
} }
dp[] = ;
Lim = (<<n)-;
printf("Case %d: %d\n",cas ++ , DFS(Lim));
}
return ;
}