UVA 11008 Antimatter Ray Clearcutting 状压DP

来源:互联网 发布:阿里云代备案管理系统 编辑:程序博客网 时间:2024/06/05 18:01

预处理出所有在一条直线的树。在记忆化中每次枚举每2棵树形成的直线。

#include <map>#include <set>#include <list>#include <cmath>#include<cctype>#include <ctime>#include <deque>#include <stack>#include <queue>#include <cstdio>#include <string>#include <vector>#include<climits>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>#define LL long long#define PI 3.1415926535897932626using namespace std;int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}#define MAXN 17int s[MAXN][MAXN];int dp[1<<MAXN];int N,M;int x[MAXN],y[MAXN];void init(){    for (int i=0;i<N;i++)        scanf("%d%d",&x[i],&y[i]);    memset(s,0,sizeof(s));    memset(dp,-1,sizeof(dp));    for (int i=0;i<N;i++)        for (int j=i+1;j<N;j++)    {        s[i][j]|=(1<<i);        s[i][j]|=(1<<j);        for (int k=0;k<N;k++)        {            if (k==i || k==j) continue;            if ((y[j]-y[i])*(x[j]-x[k])==(y[j]-y[k])*(x[j]-x[i]))                s[i][j]|=(1<<k);        }    }}int calcu(int sta){    if (dp[sta]!=-1) return dp[sta];    int cnt=0;    for (int i=0;i<N;i++) if (sta&(1<<i)) cnt++;    if (cnt<=N-M) return dp[sta]=0;    if (cnt==1)return dp[sta]=1;    dp[sta]=INT_MAX;    for (int i=0;i<N;i++)        if (sta&(1<<i))    {        for (int j=i+1;j<N;j++)            if (sta&(1<<j))            {                dp[sta]=min(dp[sta],1+calcu(sta&(~s[i][j])));            }    }    return dp[sta];}int main(){    //freopen("sample.txt","r",stdin);    int T,kase=1;    scanf("%d",&T);    while (T--)    {        scanf("%d%d",&N,&M);        init();        int limit=(1<<N)-1;        calcu(limit);        printf("Case #%d:\n%d\n",kase++,dp[limit]);        if (T) putchar('\n');    }    return 0;}


0 0