【除草】【hnoi】精简题解

好久没写了。到目前为止也算是刷完了hnoi07-12的题,精简题解第三弹(大多数代码好像都没存就不贴了)


 

2007:07年的题目略奇葩,刚开始做就被虐爆了啊>_<

海盗分宝  

  题意不明觉厉。。。

最小矩形覆盖

  裸的凸包+旋转卡壳。第一道正经的计算几何。另外这题精度巨卡,建议对着数据调。有关旋转卡壳当时做过ppt,这就不写了。

  代码:

  1 #include<stdio.h>

  2 #include<math.h>

  3 #include<iostream>

  4 #include<algorithm>

  5 #include <cmath>

  6 

  7 #define DEBUG

  8 

  9 

 10 #define INF (99999.0)

 11 #define MAXN (50000+10)

 12 #define Next(p) ((p+1)%n)

 13 using namespace std;

 14 #define EPS 1e-4

 15 struct point {

 16     double x,y;

 17     point(double a,double b) {x=a;y=b;}

 18     point(){}

 19 };

 20 typedef struct point point;

 21 typedef struct point vector;

 22 vector xx=point(1,0),yy=point(0,1);

 23 bool cmp(point a,point b){

 24     if (a.x==b.x)   return a.y<b.y;

 25     return a.x<b.x;

 26 }

 27 bool cmp2(point a,point b){

 28     if (a.y==b.y)   return a.x<b.x;

 29     return a.y<b.y;

 30 }

 31 bool cmp3(point a,point b){

 32     if (a.x==b.x)   return a.y>b.y;

 33     return a.x<b.x;

 34 }

 35 vector operator + (vector A,vector B) {

 36     return vector(A.x+B.x,A.y+B.y);

 37 }

 38 vector operator - (vector A,vector B) {

 39     return vector(A.x-B.x,A.y-B.y);

 40 }

 41 vector operator * (double k,vector A) {

 42     return vector(A.x*k,A.y*k);

 43 }

 44 double Dot(vector A,vector B) {

 45     return A.x*B.x+A.y*B.y;

 46 }

 47 double Cross(vector A,vector B) {

 48     return A.x*B.y-B.x*A.y;

 49 }

 50 double Len(vector A) {

 51     return sqrt(Dot(A,A));

 52 }

 53 double Angle(vector A,vector B) {

 54     return acos(Dot(A,B)/Len(A)/Len(B));

 55 }

 56 vector Rotate(vector A,double rad) {

 57     return vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));

 58 }

 59 int ConvexHull(point *p,int n,point *ch) {

 60     int i;

 61     sort(p,p+n,cmp);

 62     int m=0;

 63     for (i=0; i<n; i++) {

 64         while (m>1&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;

 65         ch[m++]=p[i];

 66     }

 67     int k=m;

 68     for (i=n-2; i>=0; i--) {

 69         while (m>k&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;

 70         ch[m++]=p[i];

 71     }

 72     if (n>1)    m--;

 73     return m;

 74 }

 75 double Rotating_Calipers(point *p,int n,point &A,point &B){//double p;

 76     int i;

 77     double D=-INF;

 78     int a,b;//a,b is point of A & B;

 79     A=B=p[0];

 80     for (i=0;i<n;i++){

 81         if (p[i].y>A.y)    {A=p[i];a=i;}

 82         if (p[i].y<B.y)    {B=p[i];b=i;}

 83     }

 84     for (int KK=0;KK<=n;KK++){

 85         double thta1=fabs(Angle(p[Next(a)]-p[a],xx));

 86         double thta2=fabs(Angle(p[Next(b)]-p[b],xx));

 87         if (thta1<thta2){

 88             if (Len(p[Next(a)]-p[b])>D){

 89                 D=Len(p[Next(a)]-p[b]);

 90                 A=p[Next(a)];B=p[b];

 91             }

 92             if (Len(p[a]-p[b])>D){

 93                 D=Len(p[a]-p[b]);

 94                 A=p[a];B=p[b];

 95             }

 96             a=Next(a);

 97         }

 98         if (thta1>thta2){

 99             if (Len(p[b]-p[a])>D){

100                 D=Len(p[b]-p[a]);

101                 A=p[b];B=p[a];

102             }

103             if (Len(p[Next(b)]-p[a])>D){

104                 D=Len(p[Next(b)]-p[a]);

105                 A=p[Next(b)];B=p[a];

106             }

107             b=Next(b);

108         }

109         if (thta1==thta2){

110             if (Len(p[a]-p[b])>D){

111                 D=Len(p[a]-p[b]);

112                 A=p[a];B=p[b];

113             }

114             if (Len(p[Next(a)]-p[b])>D){

115                 D=Len(p[Next(a)]-p[b]);

116                 A=p[Next(a)];B=p[b];

117             }

118             if (Len(p[a]-p[Next(b)])>D){

119                 D=Len(p[a]-p[Next(b)]);

120                 A=p[a];B=p[Next(b)];

121             }

122             if (Len(p[Next(a)]-p[Next(b)])>D){

123                 D=Len(p[Next(a)]-p[Next(b)]);

124                 A=p[Next(a)];B=p[Next(b)];

125             }

126             a=Next(a);

127             b=Next(b);

128         }

129     }

130     return D;

131 }

132 int main() {

133     int n;

134     scanf("%d",&n);

135     point p[MAXN];

136     for(int i=0; i<n; i++) {

137         scanf("%lf%lf",&p[i].x,&p[i].y);

138     }

139     point ch[MAXN],A,B;

140     int ct=ConvexHull(p,n,ch);

141 

142     #ifdef DEBUG_1

143     for (int i=0;i<ct;i++){

144         cout<<p[i].x<<" "<<p[i].y<<endl;

145     }

146     cout<<ct<<endl;

147     #endif // DEBUG

148 

149 

150     double D=Rotating_Calipers(ch,ct,A,B);

151 

152     double S=D*D*0.5;

153 

154 

155     int bib=(int)S;

156     if (fabs(bib-S)>EPS) S=bib+1;

157     else    S=bib;

158     printf("%.5lf\n",S);

159 

160     point middle=0.5*(A+B);

161     vector ttt=middle-A;

162     vector ta,tb;

163     ta=point(-ttt.y,ttt.x);

164     tb=point(ttt.y,-ttt.x);

165     point c,d;

166     c=ta+middle;

167     d=tb+middle;

168 

169     point last[10];

170     last[0]=A;last[1]=B;last[2]=c;last[3]=d;

171     for (int i=0;i<=3;i++){

172         int fx=(int)last[i].x;

173         int fy=(int)last[i].y;

174         if (fabs(fx-last[i].x)>EPS) last[i].x=fx+1;

175         else last[i].x=fx;

176         if (fabs(fy-last[i].y)>EPS) last[i].y=fy+1;

177         else last[i].y=fy;

178     }

179 

180     sort(last,last+4,cmp2);

181     printf("%.5lf %.5lf\n",last[0].x,last[0].y);

182 

183     sort(last+1,last+4,cmp3);

184     printf("%.5lf %.5lf\n",last[3].x,last[3].y);

185     printf("%.5lf %.5lf\n",last[2].x,last[2].y);

186     printf("%.5lf %.5lf\n",last[1].x,last[1].y);

187 

188     //find the other two point;

189     return 0;

190 }
View Code

胜负一子

  又不明觉厉了囧。。

神奇游乐园

  裸的插头DP。话说当时还没有陈丹琦的论文呢

分裂游戏

  这是一个叫什么什么博弈的东西,反正是经典博弈。

  思路很巧妙,把每个石子看成是一个独立游戏就可以SG了。

紧急疏散

  好题。一看就是网络流构图,但重点是流量上限应该是动态增加的。处理方法和正常的网络流一样。

梦幻岛的宝石

  背包DP,对二进制位进行DP。jwc写了一个神奇的分层DP。。我的DP还是弱啊。

所罗门的咒语

  不明觉厉第三弹。。Orz clj


 

2008:08年的题比07强,但是有很多以前没学过的东西

可见直线

  继续裸的计算几何。半平面交,注意边界直线一定要取的非常远。

明明的烦恼

  prufer编码。这个还没太理解。

越狱

  捉鸡的组合计数。不说了

神奇的国度

  弦图的贪心染色。可以看cdq的论文,或者组合数学上也有讲

GT考试

  kmp+矩阵

洗牌

  Burnside引理+DP。又跪在DP上了

玩具装箱

  以前写过详细的斜率优化。现在感觉用动态凸包的思想比较好理解。好像是数据水了,乱搞也能过

  看这里

 

遥远行星

  利用精度乱搞?给神题跪了


2009:09年的题还可以吧

梦幻布丁

  链表+启发式合并。以前也写过。看这里

通往城堡之路

  科♂学的调整。利用贪心思想确定初始解后进行调整

有趣的数列

  打个表发现是Catalan数。

最小圈

  二分答案改边权a[i]-b[i]*ans,判负环即可


 

2010:这周去ACM了,所以题是选着做的。(然后ACM被虐爆了T_T)

合唱队

  这就是DP啦

平面图判定

  环内和环外对应二分图的两侧,匹配或者2-SAT

物品调度

  知道了序列就是是贪心,关键在于求序列。看了题解,用双端链表维护,按GCD分类讨论。

公交线路

  压缩状态。没做

取石子游戏

  贪心。当时没做

城市建设

  动态最小生成树,离线搞。论文题

弹飞绵羊

  动态树或者LCT,都太麻烦。。

  直接分块,块状数组O(n*sqrt(n))

矩阵

  搜索优化?也没做


2011:难度上升,但还是可做的

数学作业

  矩阵加速递推。直接用矩阵表示不了,按位分别搞

勾股定理

  不明觉厉*4。。看看了看题解觉得好神啊。。。

赛车游戏

  贪心。利用柯西不等式可证明

括号修复

  splay维护序列,和05年noi那道题一样。暴力30分,感觉可以分块?

任务调度

  太神了!模拟退火!RP-完全问题!

XOR路径和

  计算对于期望的贡献,然后解方程

数矩形

  简单几何

卡农

  其实一点也不难,就是想出来也不确定对不对。囧。

  这个题解讲的很明白了


2012:最后一年,感觉是做的最好的。

双十字

  染色然后记录前缀和,组合计数

与非

  按位DP。不太会

排队

  简单的排列组合。捆绑,插空,容斥什么的。需要高精度,不想写了然后突然发现BZOJ上可以交python。于是你懂得。

  代码:

 1 #!/usr/bin/python

 2 # Filename: queue.py

 3 n,m=raw_input().split()

 4 n=int(n)

 5 m=int(m)

 6 def fac(a):

 7     if a==0:

 8         return 1

 9     ans=1

10     for i in range(1,a+1):

11         ans=ans*i

12     return ans

13 

14 def A(a,b):

15     return fac(a)/fac(a-b)

16 

17 if n==0:

18     print 0

19 elif m>n+3:

20     print 0

21 else:

22     print A(n,n)*(A(n+1,2)*A(n+3,m)+A(2,2)*A(n+1,1)*A(n+3-1,m-1)*m)

23 exit (0)
View Code

矿场搭建

  容易发现跟割点有关。于是有两种方法:

  删去所有割点后剩下了若干个块,那么答案就是 只与一个割点相连的块数,特殊情况若没有割点答案是2(注意不是1),复杂度O(m)

  另一种做法是直接枚举删去的点然后连通分量缩环,取最多的块数即可,复杂度O(n2)

  显然这题数据水了,两种方法都能过

三角形覆盖问题

  simpson可以搞,据说只有50分?

  注意到坐标范围不大,那么可以利用梯形剖分的思想暴力扫描线。每次扫描线+1(注意不用离散,离散了就麻烦了),然后用双端链表维护三角形,开一个数组暴力维护覆盖线段个数。

射箭

  首先设方程,因为过原点所以只有两个未知参数a和b。二份答案后列出2*ans个不等式,就变成了裸的半平面交。

  我一开始想差分约束了,显然不对。注意差分约束的不等式里没有系数,必须是x1-x2这样的。有系数的只能半平面交

永无乡

  显然的启发式合并平衡树

集合选数

  做法很神。构造出一个矩阵后就可以状压DP了。网上有很多讲的清楚的题解。

 

 

 

 

你可能感兴趣的:(题解)