LightOJ1018- Brush (IV) -状态压缩,DFS

来源:互联网 发布:精通 d3.js 第2版 pdf 编辑:程序博客网 时间:2024/04/29 03:00

题目大意:在二维平面坐标系上给你n的点,问你最少能用几条直线把他们都包括里面;

题目解析:首先我们要预处理所有的直线出来,令s[i][j]表示由点i和点j所确定的直线能经过的点的集合,为此我们需要暴力n^3处理出来,接下来就是状态dp了,如果我们不用记忆化搜索DFS就会超时,所以只能DFS了,DFS中的break很关键,很抽象需要自行体会;

AC代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>#include<vector>#include<map>using namespace std;const int inf=0x3fffffff;int dp[1<<16],n;struct point{int x,y;}p[16];int s[17][17];int dfs(int st){if(!st) return dp[st]=0;if(dp[st]!=inf)return dp[st];int temp=st,cnt=0;while(temp!=0){cnt+=temp%2;temp/=2;} if(cnt<=2)return dp[st]=1;int ans=inf,i,j;for(i=0;i<n;i++){if(st&(1<<i)){for(j=i+1;j<n;j++){if(st&(1<<j)){ans=min(ans,dfs(st^(st&s[i][j]))+1);}}break;}}return dp[st]=ans;}int main(){int cas,c,i,j,k,l,len,cnt,temp;cin>>cas;for(c=1;c<=cas;c++){memset(s,0,sizeof(s));scanf("%d",&n);for(i=0;i<n;i++){scanf("%d%d",&p[i].x,&p[i].y);}for(i=0;i<n;i++){for(j=i+1;j<n;j++){for(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))s[i][j]=s[j][i]|=(1<<k);}}}len=1<<n;for(i=0;i<len;i++)dp[i]=inf;for(i=0;i<n;i++){for(j=i+1;j<n;j++)if(s[i][j]!=0)dp[s[i][j]]=1;}printf("Case %d: %d\n",c,dfs(len-1));}return 0;}


0 0
原创粉丝点击