【除草】【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了。网上有很多讲的清楚的题解。

 

 

 

 

posted @ 2013-06-02 15:48  wsc500  阅读(567)  评论(0编辑  收藏  举报