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

方法:

显然是一个状态压缩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. C++类中使用new及delete小例子(续)

    在该示例中我们显式定义了复制构造函数来代替默认复制构造函数, 在该复制构造函数的函数体内, 不是再直接将源对象所申请空间的地址赋值给被初始化的对象, 而是自己独立申请一处内存后再将源对象的属性复制过来 ...

  2. HDU 6058 Kanade's sum 二分,链表

    Kanade's sum Problem Description Give you an array A[1..n]of length n. Let f(l,r,k) be the k-th larg ...

  3. 关于Cascading

    Cascading是一个开源的Java库和应用程序编程接口(API),它为MapReduce提供了一个抽象层.它允许开发者构建出能在Hadoop集群上运行的复杂的.关键任务的数据处理应用. Casca ...

  4. 使用a标签下载文件,而不是直接打开,使用属性 download

    有的时候,下载的链接文件如果是普通文件类型,如txt,我们下载文件的时候,有的浏览器不会弹出下载框,.而是直接打开了该文件. 针对这种情况,我们只需要在a标签上加上download属性即可显示下载框. ...

  5. POJ3278 Catch That Cow —— BFS

    题目链接:http://poj.org/problem?id=3278 Catch That Cow Time Limit: 2000MS   Memory Limit: 65536K Total S ...

  6. ASP.NET Session and Forms Authentication and Session Fixation

    https://peterwong.net/blog/asp-net-session-and-forms-authentication/ The title can be misleading, be ...

  7. poj 1724 ROADS 解题报告

    题目链接:http://poj.org/problem?id=1724 题目意思:给出一个含有N个点(编号从1~N).R条边的有向图.Bob 有 K 那么多的金钱,需要找一条从顶点1到顶点N的路径(每 ...

  8. redhat 关机注销命令详解

    一.注销,关机,重启 注销系统的logout命令 1,Logout 注销是登陆的相对操作,登陆系统后,若要离开系统,用户只要直接下达logout命令即可: [root@localhost root]# ...

  9. 基于 Laravel 5 构建的、支持模块化和多语言的 CMS —— AsgardCMS

    1.简介 AsgardCMS 是基于 Laravel 5 构建的.支持模块化和多语言的CMS. 官网:https://asgardcms.com/ Github:https://github.com/ ...

  10. Linux的终端类型

    终端是一个很重要的外设,用过终端设备的人都知道如果设备类型不对就会有乱字符,也可用仿真终端软件如netterm试验一下,Linux的终端信息放在 /usr/share/terminfo下,在这个目录的 ...