Light OJ 1018 - Brush (IV)

题目大意:

    一个二维平面上有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\n",cas ++ , DFS(Lim));
    }
    return 0;
}

 

posted @ 2015-10-23 16:11  向前走丶不回首  阅读(249)  评论(0编辑  收藏  举报