题目大意:
一个二维平面上有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+7; const int maxn = 20; const int MOD = 9973; int Line[maxn][maxn]; int dp[70000], n; struct node { int x, y; } P[maxn]; int DFS(int sta) { if(dp[sta] != - 1) return dp[sta]; dp[sta] = INF; int cnt = 0; for(int i=0; i<n; i++) if( (sta&(1<<i)) ) cnt ++; if(cnt == 0) return dp[sta] = 0; else if(cnt <= 2) return dp[sta] = 1; for(int a=0; a<n; a++) { if( (sta&(1<<a)) ) { for(int b=a+1; b<n; b++) { if((sta&(1<<a)) == 0 ) continue; int newSta = (sta|Line[a][b]) - Line[a][b]; dp[sta] = min(dp[sta], DFS(newSta) + 1); } break;///此处是优化 } } return dp[sta]; } int main() { int T, Lim, cas = 1; scanf("%d", &T); while(T --) { memset(dp, -1, sizeof(dp)); memset(Line, 0, sizeof(Line)); scanf("%d",&n); for(int i=0; i<n; i++) scanf("%d %d", &P[i].x, &P[i].y); for(int i=0; i<n; i++) { Line[i][i] = (1<<i); for(int j=i+1; j<n; j++) { for(int k=0; 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] += (1<<k); } Line[j][i] = Line[i][j]; } } dp[0] = 0; Lim = (1<<n)-1; printf("Case %d: %d ",cas ++ , DFS(Lim)); } return 0; }