题意:平面上有一些点,每刷一次可以把同一条直线上的点都刷光,问最少几次把所有点刷光。

方法:

显然是一个状态压缩dp。ans[S]表示把S集合中点刷掉的最少次数。最开始想到的方法是如果S中只有一个或两个点,那么ans[S]=1。否则枚举S中任意两点i,j作为直线上的点,并算出经过i,j的直线还过S中其他多少个点,那么ans[S]=min(ans[S],ans[S去掉那条直线经过的所有点]+1)。自然而然的就想到应该预处理出过i,j两点的直线过的其他点的集合,只需要枚举i,j和另外一个点再判是否共线即可。

这里需要用到判三点共线:https://www.zybang.com/question/ca7778a2e315afb588629121177b6772.html

A(x1,y1),B(x2,y2),C(x3,y3),则(x2-x1)×(y3-y2)=(x3-x2)×(y2-y1)

但是,这样时间复杂度是$O(T*n^3*2^n)$,还是太慢了。

观察一下可以发现:由于一个集合中所有点早晚都要刷掉,只需要指定任意一个点作为直线上的点,再枚举另一个点就行了。

那么,复杂度降低到$O(T*n^2*2^n)$。对于单组数据复杂度已经可以接受,但是由于T比较大,还是不能通过。

接下来开始卡常:

1.把循环的dp改成记忆化搜索能快许多,因为最终状态不一定需要其他所有状态的答案。

2.在开始时预处理出每个集合S的所有元素,而不是每次枚举编号判断是否在S内

3.常规(meiyong):快读,预处理左移

错误记录:

1.复杂度错误,$O(T*n^3*2^n)$

2.被卡常,用http://blog.csdn.net/kijamesqi/article/details/50533691的方法卡过去

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int x[],y[];
int T,TT,n,fff;
int ans[];
int tmp[][];
int left[];
int G[][];
void read(int&x)
{
x=;
char ch=getchar();fff=;
while(ch<''||ch>'')
{
if(ch=='-') fff=-;
ch=getchar();
}
while(ch>=''&&ch<='') x=(x<<)+(x<<)+ch-'',ch=getchar();
x*=fff;
}
int main()
{
int i,j,k,t1,t2;
for(i=;i<;i++) left[i]=(<<i);
for(i=;i<;i++)
for(k=;k<;k++)
if(i&left[k])
G[i][++G[i][]]=k;
read(T);
for(TT=;TT<=T;TT++)
{
read(n);
for(i=;i<n;i++)
read(x[i]),read(y[i]);
//memset(tmp,0,sizeof(tmp));
for(i=;i<n;i++)
for(j=i+;j<n;j++)
{
tmp[i][j]=;
t1=x[j]-x[i];
t2=y[j]-y[i];
for(k=;k<n;k++)
if(t1*(y[k]-y[j])==(x[k]-x[j])*t2)
tmp[i][j]|=left[k];
tmp[j][i]=tmp[i][j];
}
//memset(ans,0x3f,sizeof(ans));
ans[]=;
for(i=;i<left[n];i++)
{
if(__builtin_popcount(i)<=)
ans[i]=;
else
{
ans[i]=0x3f3f3f3f;
//每个点都迟早要被刷,因此枚举任意一个点作为直线上点即可,不用枚举两个
j=G[i][];
for(k=;k<=G[i][];k++)
ans[i]=min(ans[i],ans[i^(tmp[j][G[i][k]]&i)]+);
}
}
printf("Case %d: %d\n",TT,ans[left[n]-]);
}
return ;
}

Brush (IV) LightOJ - 1018的更多相关文章

  1. Lightoj 1018 - Brush (IV)

    1018 - Brush (IV)    PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB Muba ...

  2. 1018 - Brush (IV)

    1018 - Brush (IV)    PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB Muba ...

  3. Brush (III) LightOJ - 1017

    Brush (III) LightOJ - 1017 题意:有一些点,每刷一次可以将纵坐标在区间(y1,y1+w)范围内的所有点刷光,y1为任何实数.最多能刷k次,求最多共能刷掉几个点. 先将点按照纵 ...

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

    题目链接:http://lightoj.com/volume_showproblem.php? problem=1018 题意分析:平面上有不超过N个点,如今能够随意方向划直线将它们划去,问:最少要划 ...

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

    http://www.lightoj.com/volume_showproblem.php?problem=1018   Mubashwir returned home from the contes ...

  6. Light OJ 1018 - Brush (IV)

    题目大意:     一个二维平面上有N个点,一把刷子,刷一次可以把一条线上的所有点都刷掉.问最少刷多少次,可以把全部的点都刷完 状态压缩DP, 用记忆化搜索来写, 需要有个优化不然会超时. ===== ...

  7. Light oj 1018 - Brush (IV) 状态压缩

    题目大意: 给出n个点的坐标,求至少画多少掉直线才能连接所有点. 题目思路:状态压缩 首先经行预处理,求出所有状态下,那些点不在该状态内 以任意两点为端点求出这条直线的状态 枚举所有状态,找出不在当前 ...

  8. lightoj 1018 dp

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1018 #include <cstdio> #include <cst ...

  9. LightOJ1018 Brush (IV)(状压DP)

    题目大概说一个平面有n个灰尘,可以用一把刷子直直刷过去清理直线上的所有灰尘,问最少要刷几下才能清理完所有灰尘. 首先怎么刷其实是可以确定的,或者说直线有哪些是可以确定的,而最多就有C(n,2)条不一样 ...

随机推荐

  1. 12.怎样自学Struts2发送邮件和验证补充[视频]

    12.怎样自学Struts2发送邮件和验证补充[视频] 之前写了一篇"打算做一个视频教程探讨怎样自学计算机相关的技术",优酷上传不了,仅仅好传到百度云上: http://pan.b ...

  2. c++学习笔记之基础---类内声明函数后在类外定义的一种方法

    在C++的“类”中经常遇到这样的函数, 返回值类型名 类名::函数成员名(参数表){ 函数体.} 双冒号的作用 ::域名解析符!返回值类型名 类名::函数成员名(参数表) { 函数体. } 这个是在类 ...

  3. PCH in Xcode 6

    本文转载至 http://blog.csdn.net/wbdwsqwwn/article/details/40476151   新建文件 ⌘+N 选择 iOS/Mac -> Other -> ...

  4. [rabbitmq-discuss] Exactly Once Delivery

    [rabbitmq-discuss] Exactly Once Delivery http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/2010-A ...

  5. C、C++混合编程之extern "C"

    为何要“混合编程”?举个例子: CHeader.h #ifndef C_HEADER_H #define C_HEADER_H void func(); #endif CHeader.c #inclu ...

  6. 利用CoreTelephony获取用户当前网络状态(判断2G,3G,4G)

    前言: 在项目开发当中,往往需要利用网络.而用户的网络环境也需要我们开发者去注意,根据不同的网络状态作相应的优化,以提升用户体验. 但通常我们只会判断用户是在WIFI还是移动数据,而实际上,移动数据也 ...

  7. elasticsearch索引查询,日志搜素

    索引查询 http://10.199.137.115:9200/_cat/indices?format=json 返回json字符串的索引状态 增加索引名称过滤 http://10.199.137.1 ...

  8. dedecms列表页如何调用栏目关键词和描述

    问:dedecms列表页如何调用栏目关键词和描述 答:有人问起dedecms列表页如何调用栏目关键词和描述.解答如下: 自己实验了下总结方法如下:(以下方法使用于栏目封面和列表和内容页,其他的地方没有 ...

  9. MYSQL进阶学习笔记六:MySQL视图的创建,理解及管理!(视频序号:进阶_14,15)

    知识点七:MySQL视图的创建(14) 视图的定义: 什么是视图: 视图数由查询结果形成的一张虚拟的表. 什么时候要用到视图? 如果某个查询结果出现的非常频繁,也就是,要经常拿这个查询结果来做子查询. ...

  10. Silverlight中使用MVVM(4)

    Silverlight中使用MVVM(1)--基础 Silverlight中使用MVVM(2)—提高 Silverlight中使用MVVM(3)—进阶 Silverlight中使用MVVM(4)—演练 ...