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;
}
时间: 2024-10-04 18:14:50

Light OJ 1018 - Brush (IV)的相关文章

[DP] Light Oj 1017 Brush(III)

题目为 light oj 1017. 现在是凌晨两点二十分,我却毫无睡意,这题折腾了我一个晚上,一直没有做对,最后发现转移方程忽略了一个重要的条件,泪奔-. 干脆不睡觉,写一篇题解警醒自己,也算是对于自己考虑问题智障的惩罚. 我真是个智障 0 s 0 ..... 题目大意是 , 给你N个二维坐标上的点 (x,y) , 每一个点代表一个污渍,现在有一把宽度为 W 的刷子,平行于 x 轴移动 K 次,问,最多能擦掉多少污渍. 很明显这题和x坐标一点关系都没有(因为刷子沿着平行x轴移动,并可以移动无限

(状压) Brush (IV) (Light OJ 1018)

http://www.lightoj.com/volume_showproblem.php?problem=1018 Mubashwir returned home from the contest and got angry after seeing his room dusty. Who likes to see a dusty room after a brain storming programming contest? After checking a bit he found an

[LightOJ 1018]Brush (IV)[状压DP]

题目链接:http://lightoj.com/volume_showproblem.php?problem=1018 题意分析:平面上有不超过N个点,现在可以任意方向划直线将它们划去,问:最少要划几次可以把所有的点划去? 解题思路:我们可以使用集合S表示:有哪些点还没有被划掉,然后转移 dp[s] = min(dp[s &(~line[i][j])]) + 1;这里涉及到line[i][j]的处理,它代表的是在i点和j点构成的直线上一共有几个点,需要预先处理.边界条件就是S中集合元素 >0

Light OJ 1019 - Brush (V)(图论-dijkstra)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1019 题目大意:Tanvir想从节点1的位置走到节点n的位置, 输出最短距离, 如果不存在输出"Impossible". 解题思路:dijkstra模版题 代码如下: #include<bits/stdc++.h> using namespace std; typedef long long LL; const int INF = 0x3f3f3f3f;

light oj 1236 【大数分解】

给定一个大数,分解质因数,每个质因子的个数为e1,e2,e3,--em, 则结果为((1+2*e1)*(1+2*e2)--(1+2*em)+1)/2. //light oj 1236 大数分解素因子 #include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <math.h> #include <ctype.h> #i

[2016-04-21][light]OJ[1234][Harmonic Number]

时间:2016-04-21 22:18:26 星期四 题目编号:[2016-04-21][light]OJ[1234][Harmonic Number] 题目大意:求∑nk=11kn∈(1,108),精确到10?8求∑k=1n1kn∈(1,108),精确到10?8 分析: 想法是打表,然后输出,但是直接打表会爆内存 解决办法,就是每隔100个来打表,节省1100的空间,然后从那个值开始计算到当前值解决办法,就是每隔100个来打表,节省1100的空间,然后从那个值开始计算到当前值 对应的整百就是n

Light OJ 1411 Rip Van Winkle`s Code 线段树成段更新

题目来源:Light OJ 1411 Rip Van Winkle`s Code 题意:3中操作 1种查询 求区间和 其中每次可以把一段区间从左到右加上1,2,3,...或者从右到左加上...3,2,1 或者把某个区间的数都置为v 思路:我是加了6个域 add是这段区间每个数都要加上add  add是这么来的 对与123456...这个等差数列 可能要分为2个区间 那么我就分成123和123 两个右边的等差数列每个数还应该加上3 所以右区间add加3 v是这个区间都要置为v 他的优先级最高 b是

Light OJ 1168 Wishing Snake 强连通缩点+哈密顿通路

题目来源:Light OJ 1168 Wishing Snake 题意:有点难看懂题意 看了一个小时再加别人的代码才懂意思 从0开始 输入的那些每一对u v 都要经过 就是从0到到达那些点 思路:首先缩点 每一个强连通分量里面的点都是可达的 缩点后的图是有向无环图 如果从0这个强连通分量可以出去到2个强连通分量 那么这两个强连通分量是不可能相互可达 所以可行的方案就是所有的强连通分量连成一线 一个一个串起来 除了第一个 出度是1入度是0和最后一个出度是0入度是1 其他都是入度等于出度是1 特判只

Jan&#39;s light oj 01--二分搜索篇

碰到的一般题型:1.准确值二分查找,或者三分查找(类似二次函数的模型). 2.与计算几何相结合答案精度要求比较高的二分查找,有时与圆有关系时需要用到反三角函数利用 角度解题. 3.不好直接求解的一类计数问题,利用二分直接枚举可能的结果,再检查是否符合题目要求. 4.区间求解,即利用两次二分分别查找有序序列左右上下限,再求差算出总个数. 题型知识补充: 1. 三分的一般写法: 1 double thfind(double left,double right) 2 { 3 double midmid