lightoj 1018 dp
题目链接:http://lightoj.com/volume_showproblem.php?problem=1018
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> #include <algorithm> #include <queue> #include <vector> using namespace std; const int maxe = 50000; const int maxn = 16; const int INF = 0x3f3f3f; int X[maxn],Y[maxn]; int S[maxn][maxn]; int T,N; int dp[1<<maxn]; int a[1<<maxn]; int Cross(int x1,int y1,int x2,int y2){ return x1*y2 - y1 * x2; } void init(){ for(int i=0;i<maxn;i++) a[1<<i]=i; } int dfs(int x){ //求点集S。 if(dp[x]!=-1) return dp[x]; int i=a[x&-x]; //点集S的最低位上的点。 dp[x]=INF; for(int k=x-(x&-x);k;k-=k&-k){ //S-(S&-S)是去除i后的点集。 int j=a[k&(-k)]; dp[x]=min(dp[x],dfs(x^(S[i][j]&x))+1); } return dp[x]; } int main() { //freopen("E:\\acm\\input.txt","r",stdin); init(); cin>>T; for(int cas=1;cas<=T;cas++){ scanf("%d",&N); for(int i=0;i<N;i++) scanf("%d %d",&X[i],&Y[i]); memset(S,0,sizeof(S)); for(int i=0;i<N;i++) for(int j=i+1;j<N;j++){ for(int k=0;k<N;k++){ if(!Cross(X[j]-X[i],Y[j]-Y[i],X[k]-X[i],Y[k]-Y[i])) S[i][j] |= (1<<k); //i,j所在直线上其他点的集合。 } S[j][i] = S[i][j]; } int ALL = (1<<N)-1; memset(dp,-1,sizeof(dp)); dp[0] = 0; for(int i=0;i<N;i++) dp[1<<i] = 1; printf("Case %d: %d\n",cas,dfs(ALL)); } }