COJ1107 UVA12296 Pieces and Discs 2011湖南省赛H题

把每个交点映射为单独的id,map去重。对每个点建立相邻点的链表。枚举点,用相邻点链表找最左点,迭代绕出凸包,枚举圆判凸包与圆相交。

  1 #include<stdio.h>

  2 #include<string.h>

  3 #include<stdlib.h>

  4 #include<math.h>

  5 #include<vector>

  6 #include<algorithm>

  7 #include<iostream>

  8 #include<map>

  9 using namespace std;

 10 const int maxn = 41;

 11 const int maxm = maxn * maxn;

 12 const double eps = 1e-8;

 13 const double pi = acos(-1.0);

 14 int dcmp(double x)

 15 {

 16     if(x < -eps) return -1;

 17     return x > eps;

 18 }

 19 struct Point

 20 {

 21     double x, y, r;

 22     bool operator <(const Point &b)const

 23     {

 24         if(dcmp(x - b.x) == 0)

 25             return y < b.y;

 26         return x < b.x;

 27     }

 28 };

 29 typedef struct

 30 {

 31     Point s, e;

 32     double ang, d;

 33 } Line;

 34 

 35 inline double det(double x1, double y1, double x2, double y2)

 36 {

 37     return x1 * y2 - x2 * y1;

 38 }

 39 double cross(Point a, Point b, Point c)

 40 {

 41     return det(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y);

 42 }

 43 Point MakePoint(double xx, double yy)

 44 {

 45     Point res;

 46     res.x = xx, res.y = yy;

 47     return res;

 48 }

 49 

 50 

 51 int n, m, L, W, pnum;

 52 vector<Point> ap;

 53 vector<int> lp[maxn], adjp[maxm];

 54 vector<Line> l;

 55 vector<double> ans[maxn];

 56 map<Point, int> M;

 57 Point c[maxn];

 58 bool visp[maxm];

 59 

 60 Line SetLine(Point a, Point b)

 61 {

 62     Line l;

 63     l.s = a;

 64     l.e = b;

 65     l.ang = atan2(b.y - a.y, b.x - a.x);

 66     if(dcmp(a.x - b.x)) l.d = (a.x * b.y - b.x * a.y) / fabs(a.x - b.x);

 67     else l.d = (a.x * b.y - b.x * a.y) / fabs(a.y - b.y);

 68     return l;

 69 }

 70 double dotdet(double x1, double y1, double x2, double y2)

 71 {

 72     return x1 * x2 + y1 * y2;

 73 }

 74 double dot(Point a, Point b, Point c)

 75 {

 76     return dotdet(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y);

 77 }

 78 int betweenCmp(Point a, Point b, Point c)

 79 {

 80     return dcmp(dot(a, b, c));

 81 }

 82 bool segcross(Point a, Point b, Point c, Point d, Point &p)

 83 {

 84     double s1, s2, s3, s4;

 85     int d1, d2, d3, d4;

 86     d1 = dcmp(s1 = cross(a, b, c));

 87     d2 = dcmp(s2 = cross(a, b, d));

 88     d3 = dcmp(s3 = cross(c, d, a));

 89     d4 = dcmp(s4 = cross(c, d, b));

 90     if((d1 ^ d2) == -2 && (d3 ^ d4 == -2))

 91     {

 92         p.x = (c.x * s2 - d.x * s1) / (s2 - s1);

 93         p.y = (c.y * s2 - d.y * s1) / (s2 - s1);

 94         return true;

 95     }

 96     if(d1 == 0 && betweenCmp(c, a, b) <= 0)

 97     {

 98         p = c;

 99         return true;

100     }

101     if(d2 == 0 && betweenCmp(d, a, b) <= 0)

102     {

103         p = d;

104         return true;

105     }

106     if(d3 == 0 && betweenCmp(a, c, d) <= 0)

107     {

108         p = a;

109         return true;

110     }

111     if(d4 == 0 && betweenCmp(b, c, d) <= 0)

112     {

113         p = b;

114         return true;

115     }

116     return false;

117 }

118 

119 bool CrossPoint(const Line &la, const Line &lb, Point &p)

120 {

121     return segcross(la.s, la.e, lb.s, lb.e, p);

122 }

123 bool Parallel(const Line &la, const Line &lb)

124 {

125     return !dcmp( (la.e.x - la.s.x) * (lb.e.y - lb.s.y) -

126                   (la.e.y - la.s.y) * (lb.e.x - lb.s.x) );

127 }

128 double PolygonArea(vector<int> p)

129 {

130     if(p.size() < 4) return 0.0;

131     double s = ap[p[0]].y * (ap[p[p.size() - 2]].x - ap[p[1]].x);

132     for(int i = 1; i < p.size() - 1; ++ i)

133         s += ap[p[i]].y * (ap[p[i - 1]].x - ap[p[i + 1]].x);

134     return fabs(s * 0.5);

135 }

136 inline double CalLen(double a, double b)

137 {

138     return sqrt(a * a + b * b);

139 }

140 inline double CalDis(Point a, Point b)

141 {

142     return CalLen(a.x - b.x, a.y - b.y);

143 }

144 inline bool InCir(Point a, Point b)

145 {

146     return dcmp(CalDis(a, b) - b.r) < 0;

147 }

148 inline bool OnCir(Point a, Point b)

149 {

150     return dcmp(CalDis(a, b) - b.r) == 0;

151 }

152 double DisPtoL(Point p, Point a, Point b)

153 {

154     return fabs(cross(p, a, b)) / CalDis(a, b);

155 }

156 bool EqualPoint(Point a, Point b)

157 {

158     return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;

159 }

160 bool SegIntersCircle(Point a, Point b, Point c)

161 {

162     Point t = c;

163     t.x += a.y - b.y;

164     t.y += b.x - a.x;

165     return cross(a, c, t) * cross(b, c, t) < eps &&

166            DisPtoL(c, a, b) - c.r < -eps;

167 }

168 bool JudgePiece(int i, vector<int> ps)

169 {

170     int j, k, cnt = 0;

171     for(j = 1; j < ps.size(); ++ j)

172     {

173         if(InCir(ap[ps[j]], c[i])) return true;

174         else if(OnCir(ap[ps[j]], c[i])) ++ cnt;

175     }

176     if(cnt >= 2) return true;

177     for(j = 1; j < ps.size(); ++ j)

178         for(k = j + 1; k < ps.size(); ++ k)

179         {

180             if(SegIntersCircle(ap[ps[j]], ap[ps[k]], c[i]))

181                 return true;

182         }

183     for(j = 1; j < ps.size(); ++ j)

184         if(cross(ap[ps[j - 1]], ap[ps[j]], c[i]) < -eps) return false;

185     return true;

186 }

187 void FindPiece(int s0, int s1)

188 {

189     vector<int> ps;

190     int i, j, nex = s1, ori = s0;

191     double s;

192     ps.push_back(s0);

193     ps.push_back(s1);

194     while(nex != ori)

195     {

196         nex = -1;

197         for(i = 0; i < adjp[s1].size(); ++ i)

198         {

199             if(EqualPoint(ap[adjp[s1][i]], ap[s0])) continue;

200             if(cross(ap[s0], ap[s1], ap[adjp[s1][i]]) > -eps &&

201                     (nex == -1 || cross(ap[s1], ap[nex], ap[adjp[s1][i]]) > eps))

202                 nex = adjp[s1][i];

203         }

204         if(nex != -1 && (!visp[nex] || nex == ori))

205             ps.push_back(nex);

206         else return;

207         s0 = s1, s1 = nex;

208     }

209     s = PolygonArea(ps);

210     if(!dcmp(s)) return;

211     for(i = 0; i < m; ++ i)

212         if(JudgePiece(i, ps))

213             ans[i].push_back(s);

214 }

215 

216 bool cmp(const int &a, const int &b)

217 {

218     if(dcmp(ap[a].x - ap[b].x) == 0)

219         return ap[a].y < ap[b].y;

220     return ap[a].x < ap[b].x;

221 }

222 int main()

223 {

224     int i, j, pnum;

225     double sx, sy, ex, ey;

226     while(scanf("%d%d%d%d", &n, &m , &L, &W), n | m | L | W)

227     {

228         l.clear();

229         n += 4;

230         M.clear();

231         ap.clear();

232         memset(visp, 0, sizeof(visp));

233         l.push_back(SetLine(MakePoint(0, 0), MakePoint(L, 0)));

234         l.push_back(SetLine(MakePoint(L, 0), MakePoint(L, W)));

235         l.push_back(SetLine(MakePoint(L, W), MakePoint(0, W)));

236         l.push_back(SetLine(MakePoint(0, W), MakePoint(0, 0)));

237         for(i = 4; i < n; ++ i)

238         {

239             scanf("%lf%lf%lf%lf", &sx, &sy, &ex, &ey);

240             l.push_back(SetLine(MakePoint(sx, sy), MakePoint(ex, ey)));

241         }

242         for(i = 0; i < m; ++ i)

243             scanf("%lf%lf%lf", &c[i].x, &c[i].y, &c[i].r), ans[i].clear();

244         for(i = 0; i < n; ++ i) lp[i].clear();

245         for(i = pnum = 0; i < n; ++ i)

246             for(j = i + 1; j < n; ++ j)

247             {

248                 Point tmp;

249                 if(CrossPoint(l[i], l[j], tmp))

250                 {

251                     if(!M.count(tmp))

252                         adjp[pnum].clear(), M[tmp] = pnum ++, ap.push_back(tmp);

253                     lp[i].push_back(M[tmp]);

254                     lp[j].push_back(M[tmp]);

255                 }

256             }

257         for(i = 0; i < n; ++ i)

258         {

259             sort(lp[i].begin(), lp[i].end(), cmp);

260             for(j = 1; j < lp[i].size(); ++ j)

261             {

262                 if(!EqualPoint(ap[lp[i][j]], ap[lp[i][j - 1]]))

263                 {

264                     adjp[lp[i][j]].push_back(lp[i][j - 1]);

265                     adjp[lp[i][j - 1]].push_back(lp[i][j]);

266                 }

267             }

268         }

269         for(i = 0; i < pnum; ++ i)

270         {

271             if(!visp[i])

272             {

273                 visp[i] = true;

274                 for(j = 0; j < adjp[i].size(); ++ j)

275                     if(!visp[adjp[i][j]])FindPiece(i, adjp[i][j]);

276             }

277         }

278         for(i = 0; i < m; ++ i)

279         {

280             sort(ans[i].begin(), ans[i].end());

281             printf("%d", ans[i].size());

282             for(j = 0; j < ans[i].size(); ++ j)

283                 printf(" %.2f", ans[i][j]);

284             printf("\n");

285         }

286         printf("\n");

287     }

288     return 0;

289 }

 

 

 

 

你可能感兴趣的:(uva)