记忆化搜索+状态压缩。。。。开始的时候无限的超时啊。。。。。
有一点要注意啊:
当每次选没到有消除的 i 后直接跳出循环,因为你要是通过别的两个点来经过这个i的话会重复的计算!
DFS(statu)表示 消除剩余的状态statu所需要的次数!
AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAX 0x3f3f3f3f
typedef struct{
int x, y;
}Point;
int dp[1<<16], N;
int line[20][20];
Point p[20];
int DFS( int statu ){
if( dp[statu] != MAX ){
return dp[statu];
}
if( statu == 0 ){
return dp[statu] = 0;
}
int cnt = 0;
for( int i = 0; i < N; i++ ){
if( statu & ( 1 << i ) ){
cnt++;
}
}
if( cnt <= 2 ){
return dp[statu] = 1;
}
for( int i = 0; i < N; i++ ){
if( statu & ( 1 << i ) ){
for( int j = i + 1; j < N; j++ ){
if( statu & ( 1 << j ) ){
dp[statu] = min( dp[statu], 1 + DFS( statu & line[i][j] ) );
}
}
break;//没有的话会超时!!!
}
}
return dp[statu];
}
int main(){
int T, Case = 1;
cin >> T;
while( T-- ){
cin >> N;
for( int i = 0; i < N; i++ ){
cin >> p[i].x >> p[i].y;
}
for( int i = 0; i < N; i++ ){
for( int j = i + 1; j < N; j++ ){
if( i == j ){
continue;
}
int temp = ( 1 << N ) - 1;
temp ^= ( 1 << i );
temp ^= ( 1 << j );
for( int k = 0; k < N; k++ ){
if( k == i || k == j ){
continue;
}
double a = p[k].y - p[j].y;
double b = p[k].x - p[j].x;
double c = p[j].y - p[i].y;
double d = p[j].x - p[i].x;
if( ( a * d ) == ( c * b ) ){
temp ^= ( 1 << k );
}
}
line[i][j] = temp;
}
}
memset( dp, 0x3f, sizeof( dp ) );
cout << "Case " << Case++ << ": " << DFS( ( 1 << N ) - 1 ) << endl;
}
return 0;
}