LightOJ1018 Brush (IV)(状压DP)

题目大概说一个平面有n个灰尘,可以用一把刷子直直刷过去清理直线上的所有灰尘,问最少要刷几下才能清理完所有灰尘。

  • 首先怎么刷其实是可以确定的,或者说直线有哪些是可以确定的,而最多就有C(n,2)条不一样的直线,即16*15/2=120;
  • 然后容易想到用状压DP求解,d[S]表示已经清理的灰尘的状态是S最少刷的次数;
  • 而转移就是通过枚举接下来使用那条直线,用我为人人的方式转移,
  • 另外直线包含的灰尘集合状态一开始就可以预处理出来,这样时间复杂度O(2n*n2)。

不过超时,超了800多ms。实在想不出怎么没办法。而看了网上,也是一样思路,不过转移是任意选出一个没有在S中的点,然后枚举另一个没有在S的端点,通过添加这两点构成的直线去转移,时间复杂度O(2n*n)。

我表示不解。。这样有些状态会漏吧???

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5
 6 int d[1<<16],sta[16][16];
 7 int main(){
 8     int t,n,x[16],y[16];
 9     scanf("%d",&t);
10     for(int cse=1; cse<=t; ++cse){
11         scanf("%d",&n);
12         for(int i=0; i<n; ++i){
13             scanf("%d%d",x+i,y+i);
14         }
15         if(n==1){
16             printf("Case %d: %d\n",cse,1);
17             continue;
18         }
19         for(int i=0; i<n; ++i){
20             for(int j=0; j<n; ++j){
21                 if(i==j){
22                     sta[i][j]=(1<<i);
23                     continue;
24                 }
25                 int s=0;
26                 for(int k=0; k<n; ++k){
27                     if((x[i]-x[j])*(y[j]-y[k])==(x[j]-x[k])*(y[i]-y[j])){
28                         s|=(1<<k);
29                     }
30                 }
31                 sta[i][j]=s;
32             }
33         }
34         memset(d,127,sizeof(d));
35         d[0]=0;
36         for(int i=0; i<(1<<n)-1; ++i){
37             if(d[i]>10000) continue;
38             int j=0;
39             while(j<n){
40                 if((i>>j&1)==0) break;
41                 ++j;
42             }
43             for(int k=0; k<n; ++k){
44                 if((i>>k&1)==0){
45                     d[i|sta[j][k]]=min(d[i|sta[j][k]],d[i]+1);
46                 }
47             }
48         }
49         printf("Case %d: %d\n",cse,d[(1<<n)-1]);
50     }
51     return 0;
52 }
时间: 2024-11-06 06:50:48

LightOJ1018 Brush (IV)(状压DP)的相关文章

[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

[NOIP2016]愤怒的小鸟 D2 T3 状压DP

[NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可以用它向第一象限发射一只红色的小鸟,小鸟们的飞行轨迹均为形如y=ax2+bx的曲线,其中a,b是Kiana指定的参数,且必须满足a<0. 当小鸟落回地面(即x轴)时,它就会瞬间消失. 在游戏的某个关卡里,平面的第一象限中有n只绿色的小猪,其中第i只小猪所在的坐标为(xi,yi). 如果某只小鸟的飞行

ZOJ3305Get Sauce 状压DP,

状压DP的题目留个纪念,首先题意一开始读错了,搞了好久,然后弄好了,觉得DFS可以,最后超时,修改了很久还是超时,没办法看了一下n的范围,然后觉得状压可以,但是没有直接推出来,就记忆化搜索了一下,可是一直错,莫名奇妙,然后没办法看了一下题解,发现了下面这个比较好的方法,然后按照这个方程去推,然后敲,也是WA了好多把,写的太搓了,没人家的清楚明了,唉~也算是给自己留个纪念,状压一直做的都不太好~唉~还好理解了, 参考了  http://blog.csdn.net/nash142857/articl

poj 2411 Mondriaan&#39;s Dream(状压DP)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12232   Accepted: 7142 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

(状压dp)uva 10817 Headmaster&#39;s Headache

题目地址 1 #include <bits/stdc++.h> 2 typedef long long ll; 3 using namespace std; 4 const int MAX=1e5+5; 5 const int INF=1e9; 6 int s,m,n; 7 int cost[125]; 8 //char sta[MAX]; 9 string sta; 10 int able[125]; 11 int dp[125][1<<8][1<<8]; 12 in

HDU5816 Hearthstone(状压DP)

题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5816 Description Hearthstone is an online collectible card game from Blizzard Entertainment. Strategies and luck are the most important factors in this game. When you suffer a desperate situation an

HDU 4336 容斥原理 || 状压DP

状压DP :F(S)=Sum*F(S)+p(x1)*F(S^(1<<x1))+p(x2)*F(S^(1<<x2))...+1; F(S)表示取状态为S的牌的期望次数,Sum表示什么都不取得概率,p(x1)表示的是取x1的概率,最后要加一因为有又多拿了一次.整理一下就可以了. 1 #include <cstdio> 2 const int Maxn=23; 3 double F[1<<Maxn],p[Maxn]; 4 int n; 5 int main() 6

Travel(HDU 4284状压dp)

题意:给n个城市m条路的网图,pp在城市1有一定的钱,想游览这n个城市(包括1),到达一个城市要一定的花费,可以在城市工作赚钱,但前提有工作证(得到有一定的花费),没工作证不能在该城市工作,但可以走,一个城市只能工作一次,问pp是否能游览n个城市回到城市1. 分析:这个题想到杀怪(Survival(ZOJ 2297状压dp) 那个题,也是钱如果小于0就挂了,最后求剩余的最大钱数,先求出最短路和 Hie with the Pie(POJ 3311状压dp) 送披萨那个题相似. #include <

BZOJ 1087: [SCOI2005]互不侵犯King( 状压dp )

简单的状压dp... dp( x , h , s ) 表示当前第 x 行 , 用了 h 个 king , 当前行的状态为 s . 考虑转移 : dp( x , h , s ) = ∑ dp( x - 1 , h - cnt_1( s ) , s' ) ( s and s' 两行不冲突 , cnt_1( s ) 表示 s 状态用了多少个 king ) 我有各种预处理所以 code 的方程和这有点不一样 ------------------------------------------------