2013多校训练赛第二场 总结

  昨天打多校的第二场,状态还算可以,不会像第一场那样浑浑噩噩的敲过去了。可是这次的排名却比第一次要低了。

  其实昨天比赛很不顺,主要是机房的机器不够,导致我们开局一小时后从三台机减少到只剩一台机。

  开始的时候,队友ly像开挂一样,瞬间就看懂了1002,20min敲出了代码,抢了个fb。然后就是1009,这题其实很简单,很容易可以看出就是一个二分匹配的题。题目大意是,给出一些1*2的方块,有横向和纵向放置两种,其中只可能出现横向跟纵向重叠的情况,不会横向和横向纵向和纵向重叠。要求求出,最多可以剩下多少方块,是的它们之间两两不重叠。这样子,就可以对有重叠部分的横向和纵向方块添加一条边。然后求出最大匹配,就是最少要删除的方块数目。最后的答案是n+m减去匹配的数目。

  然后就是队友卡1006了,这时,为了打破窘境(2个小时才做了2题),我去看了一下1007,好水的一道三维几何的题。这题的题意是给出一些空间圆柱,要求求出所有圆柱之间的最短距离。如果有重叠的部分,就输出Lucky。其实可以直接将圆柱看成直线,然后求出空间直线的最短距离即可。1y。

  在我过了1007以后,队友xdp也接着出了1001。最后整场比赛就就卡在1006了。在不停的给1006出数据以后,最终过了1006,然后才看到1004是简单的线段树,这时的时间已经剩下一个钟不够,最后以5题结束了比赛,线段树没有及时写出来。

  这次的组队,主要欠缺在于明明已知09是二分,结果搞了很久贪心wa了几次。

  组队的时候如果看出算法,就应该直接上那个模板,而不应该想虽然敲的简单,却不能肯定对的做法。

贴一下代码:

hdu 4619:(二分匹配的题,用了HK算法,不过因为边数比较少,可以直接用匈牙利算法。)

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <queue>
 7 #include <vector>
 8 
 9 using namespace std;
10 const int N = 1111;
11 vector<int> rel[N];
12 
13 bool overlap(int a, int b, int c, int d) {
14     if (c == a && d + 1 == b) return true;
15     if (c == a && d == b) return true;
16     if (c == a + 1 && d + 1 == b) return true;
17     if (c == a + 1 && d == b) return true;
18     return false;
19 }
20 
21 int mx[N], my[N], rx[N], ry[N];
22 int hx[N], hy[N], vx[N], vy[N];
23 queue<int> Q;
24 
25 bool HKbfs(int n) {
26     bool ret = false;
27     while (!Q.empty()) Q.pop();
28     memset(rx, 0, sizeof(rx));
29     memset(ry, 0, sizeof(ry));
30     for (int i = 0; i < n; i++) {
31         if (mx[i] == -1) Q.push(i);
32     }
33     while (!Q.empty()) {
34         int cur = Q.front();
35         Q.pop();
36         for (int i = 0; i < rel[cur].size(); i++) {
37             int t = rel[cur][i];
38             if (!ry[t]) {
39                 ry[t] = rx[cur] + 1;
40                 if (~my[t]) {
41                     rx[my[t]] = ry[t] + 1;
42                     Q.push(my[t]);
43                 } else {
44                     ret = true;
45                 }
46             }
47         }
48     }
49     return ret;
50 }
51 
52 bool HKdfs(int cur) {
53     for (int i = 0; i < rel[cur].size(); i++) {
54         int t = rel[cur][i];
55         if (ry[t] == rx[cur] + 1) {
56             ry[t] = 0;
57             if (my[t] == -1 || HKdfs(my[t])) {
58                 my[t] = cur;
59                 mx[cur] = t;
60                 return true;
61             }
62         }
63     }
64     return false;
65 }
66 
67 int HK(int n) {
68     int cnt = 0;
69     memset(mx, -1, sizeof(mx));
70     memset(my, -1, sizeof(my));
71     while (HKbfs(n)) {
72         for (int i = 0; i < n; i++) if (mx[i] == -1 && HKdfs(i)) cnt++;
73     }
74     return cnt;
75 }
76 
77 int main() {
78     int n, m;
79     while (cin >> n >> m && (n || m)) {
80         for (int i = 0; i < n; i++) cin >> hx[i] >> hy[i];
81         for (int i = 0; i < m; i++) cin >> vx[i] >> vy[i];
82         for (int i = 0; i < n; i++) {
83             rel[i].clear();
84             for (int j = 0; j < m; j++) {
85                 if (overlap(hx[i], hy[i], vx[j], vy[j])) {
86                     //cout << i << ' ' << j << endl;
87                     rel[i].push_back(j);
88                 }
89             }
90         }
91         cout << n + m - HK(n) << endl;
92     }
93     return 0;
94 }
View Code

hdu 4617:(三维几何)

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <queue>
 7 #include <vector>
 8 
 9 using namespace std;
10 
11 const double EPS = 1e-8;
12 const int N = 33;
13 inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
14 struct Point {
15     double x, y, z;
16     Point() {}
17     Point(double x, double y, double z) : x(x), y(y), z(z) {}
18     Point operator + (Point a) { return Point(x + a.x, y + a.y, z + a.z);}
19     Point operator - (Point a) { return Point(x - a.x, y - a.y, z - a.z);}
20     Point operator * (double p) { return Point(x * p, y * p, z * p);}
21     Point operator / (double p) { return Point(x / p, y / p, z / p);}
22 } pt[N][3];
23 
24 inline double dot(Point a, Point b) { return a.x * b.x + a.y * b.y + a.z * b.z;}
25 inline Point cross(Point a, Point b) { return Point(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);}
26 inline double veclen(Point x) { return sqrt(dot(x, x));}
27 inline double ptdis(Point a, Point b) { return veclen(a - b);}
28 inline Point vecunit(Point x) { return x / veclen(x);}
29 
30 bool lldis(Point p1, Point u, Point p2, Point v, double &s) {
31     double b = dot(u, u) * dot(v, v) - dot(u, v) * dot(u, v);
32     if (sgn(b) == 0) return false;
33     double a = dot(u, v) * dot(v, p1 - p2) - dot(v, v) * dot(u, p1 - p2);
34     s = a / b;
35     return true;
36 }
37 
38 double p2l(Point p, Point a, Point b) {
39     Point v1 = b - a, v2 = p - a;
40     return veclen(cross(v1, v2)) / veclen(v1);
41 }
42 
43 Point p[N], nor[N];
44 double r[N];
45 
46 int main() {
47     int T, n;
48     cin >> T;
49     while (T-- && cin >> n) {
50         for (int i = 0; i < n; i++) {
51             for (int j = 0; j < 3; j++) cin >> pt[i][j].x >> pt[i][j].y >> pt[i][j].z;
52             p[i] = pt[i][0];
53             r[i] = veclen(pt[i][0] - pt[i][1]);
54             nor[i] = cross(pt[i][1] - pt[i][0], pt[i][2] - pt[i][0]);
55         }
56         double ans = 1e10;
57         bool touch = false;
58         for (int i = 0; i < n && !touch; i++) {
59             for (int j = i + 1; j < n && !touch; j++) {
60                 double s, t, dis;
61                 if (lldis(p[i], nor[i], p[j], nor[j], s)) {
62                     lldis(p[j], nor[j], p[i], nor[i], t);
63                     Point a = p[i] + nor[i] * s;
64                     Point b = p[j] + nor[j] * t;
65                     dis = ptdis(a, b);
66                 } else dis = p2l(p[i], p[j], p[j] + nor[j]);
67                 //cout << i << ' ' << j << ' ' << dis << endl;
68                 if (dis <= r[i] + r[j]) touch = true;
69                 ans = min(ans, dis - r[i] - r[j]);
70             }
71         }
72         if (touch) puts("Lucky");
73         else printf("%.2f
", ans);
74     }
75     return 0;
76 }
View Code

hdu 4611:(模拟,队友xdp过的)

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 #define ll long long
 8 
 9 ll gcd(ll a,ll b){
10     return b?gcd(b,a%b):a;
11 }
12 ll lcm(ll a,ll b){
13     return a/gcd(a,b)*b;
14 }
15 ll myabs(ll key){
16     if(key<0) return -key;
17     return key;
18 }
19 
20 int main(){
21 //    freopen("in","r",stdin);
22     int t;
23     cin>>t;
24     while(t--){
25         ll l=0,r=0,rlcm=0,rsum=0;
26         ll n,a,b;
27         cin>>n>>a>>b;
28 //        cout<<n<<endl;
29         if(a<b) swap(a,b);
30         ll c=n%lcm(a,b);
31         do{
32 //            cout<<l<<' '<<r<<endl;
33             ll dif=myabs(l-r);
34             ll Max=min(a-l,b-r);
35 //            printf("Max = %lld, dif = %lld
",Max,dif);
36             rlcm+=Max*dif;
37 //            printf("rlcm =
38             if(c>=Max){
39                 rsum+=Max*dif;
40                 c-=Max;
41             }
42             else{
43                 rsum+=c*dif;
44                 c=0;
45             }
46             l+=Max;
47             r+=Max;
48             l%=a;
49             r%=b;
50 //            cout<<l<<' '<<r<<endl;
51         }while(l!=0 || r!=0);
52         ll f=n/lcm(a,b);
53         cout<<rlcm*f+rsum<<endl;
54     }
55     return 0;
56 }
View Code

hdu 4616:(树dp,队友ly过的)

  1 #pragma comment(linker,"/STACK:102400000,102400000")
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <algorithm>
  6 #include <queue>
  7 #include <cmath>
  8 #include <stack>
  9 typedef long long LL;
 10 
 11 const int N = 50005;
 12 using namespace std;
 13 int n,c;
 14 LL dp[N][5][5];
 15 int tot,pre[N];
 16 struct edge{
 17     int v,next;
 18 }e[N<<1];
 19 LL val[N];
 20 int trap[N];
 21 
 22 void init(){
 23     tot=0;
 24     memset(pre,-1,sizeof(pre));
 25     memset(dp,-1,sizeof(dp));
 26 }
 27 
 28 void add(int u,int v){
 29     edge E={v,pre[u]};
 30     e[tot]=E,pre[u]=tot++;
 31 }
 32 
 33 void input(){
 34     scanf("%d%d",&n,&c);
 35     int u,v;
 36     for(int i=0;i<n;i++){
 37         scanf("%I64d%d",&val[i],&trap[i]);
 38     }
 39     for(int i=1;i<n;i++){
 40         scanf("%d%d",&u,&v);
 41         add(u,v),add(v,u);
 42     }
 43 }
 44 
 45 void dfs1(int u,int fa){
 46     dp[u][trap[u]][0]=val[u];
 47     for(int i=pre[u];i!=-1;i=e[i].next){
 48         int v=e[i].v;
 49         if(v==fa) continue;
 50         dfs1(v,u);
 51         int lim;
 52         if(trap[u]) lim=c;
 53         else lim=c-1;
 54         for(int j=trap[u];j<=lim;j++){
 55             if(dp[v][j-trap[u]][0]!=-1){
 56                 if(dp[u][j][0]<=dp[v][j-trap[u]][0]+val[u]){
 57 //                    if(u==3&&j==0) printf("!!!  dp[%d][%d][0]=%lld
",v,j-trap[u],dp[v][j-trap[u]][0]);
 58                     dp[u][j][1]=dp[u][j][0];
 59                     dp[u][j][0]=dp[v][j-trap[u]][0]+val[u];
 60                 }
 61                 else{
 62                     if(dp[u][j][1]<dp[v][j-trap[u]][0]+val[u]){
 63                         dp[u][j][1]=dp[v][j-trap[u]][0]+val[u];
 64                     }
 65                 }
 66             }
 67         }
 68     }
 69 }
 70 
 71 LL res;
 72 
 73 void dfs2(int u,int fa){
 74     for(int i=0;i<=c;i++){
 75         for(int j=0;j<3;j++){
 76             res=max(res,dp[u][i][j]);
 77         }
 78     }
 79     for(int i=pre[u];i!=-1;i=e[i].next){
 80         int v=e[i].v;
 81         if(v==fa) continue;
 82         int lim=c-1;
 83         for(int j=trap[u];j<=lim;j++){
 84             if(j+trap[v]>c) continue;
 85             if(dp[u][j][0]==dp[v][j-trap[u]][0]+val[u]){
 86                 if(dp[u][j][1]!=-1) dp[v][j+trap[v]][2]=max(dp[v][j+trap[v]][2],dp[u][j][1]+val[v]);
 87 //                if(v==7&&j+trap[v]==2) printf("dp[%d][%d][1]=%lld val[%d]=%lld
",u,j,dp[u][j][1],v,val[v]);
 88 
 89             }
 90             else if(dp[u][j][0]!=-1){
 91 //                if(v==7&&j+trap[v]==2) printf("dp[%d][%d][0]=%lld val[%d]=%lld
",u,j,dp[u][j][0],v,val[v]);
 92                 dp[v][j+trap[v]][2]=max(dp[v][j+trap[v]][2],dp[u][j][0]+val[v]);
 93             }
 94 //            if(v==7&&j+trap[v]==2) printf("dp[%d][%d][2]=%lld val[%d]=%lld
",u,j,dp[u][j][2],v,val[v]);
 95             if(dp[u][j][2]!=-1) dp[v][j+trap[v]][2]=max(dp[v][j+trap[v]][2],dp[u][j][2]+val[v]);
 96         }
 97         dfs2(v,u);
 98     }
 99 }
100 
101 void get(){
102     puts("~~~~~~~~~~~~~~~~~~~~~~");
103     for(int i=3;i<=3;i++){
104         for(int j=0;j<=c;j++){
105             for(int k=0;k<3;k++){
106                 if(dp[i][j][k]!=-1) printf("dp[%d][%d][%d]=%lld
",i,j,k,dp[i][j][k]);
107             }
108         }
109     }
110 }
111 
112 int main(){
113 //    freopen("in","r",stdin);
114     int T;
115     scanf("%d",&T);
116     while(T--){
117         init();
118         input();
119         res=-1;
120         dfs1(0,-1);
121         dp[0][trap[0]][2]=0;
122         dfs2(0,-1);
123 //        get();
124         cout << res << endl;
125     }
126     return 0;
127 }
View Code

hdu 4614:(线段树,跟POJ的hotel那题相似,是比较经典的模型)

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <queue>
  7 #include <vector>
  8 
  9 using namespace std;
 10 
 11 const int N = 55555;
 12 
 13 #define lson l, m, rt << 1
 14 #define rson m + 1, r, rt << 1 | 1
 15 #define root 0, n - 1, 1
 16 
 17 int ml[N << 2], mr[N << 2], sum[N << 2], late[N << 2];
 18 int n;
 19 
 20 void up(int rt) {
 21     int ls = rt << 1, rs = rt << 1 | 1;
 22     sum[rt] = sum[ls] + sum[rs];
 23     if (ml[ls] == -1) ml[rt] = ml[rs];
 24     else ml[rt] = ml[ls];
 25     if (mr[rs] == -1) mr[rt] = mr[ls];
 26     else mr[rt] = mr[rs];
 27 }
 28 
 29 void down(int rt, int l, int r) {
 30     int ls = rt << 1, rs = rt << 1 | 1;
 31     int len = r - l + 1;
 32     int lr = len >> 1, ll = len - lr;
 33     if (~late[rt]) {
 34         sum[ls] = late[rt] * ll;
 35         sum[rs] = late[rt] * lr;
 36         if (late[rt]) {
 37             ml[ls] = ml[rs] = mr[ls] = mr[rs] = -1;
 38         } else {
 39             ml[ls] = l, mr[ls] = l + ll - 1;
 40             ml[rs] = r - lr + 1, mr[rs] = r;
 41         }
 42         late[ls] = late[rs] = late[rt];
 43         late[rt] = -1;
 44     }
 45 }
 46 
 47 void build(int l, int r, int rt) {
 48     late[rt] = -1;
 49     if (l == r) {
 50         ml[rt] = mr[rt] = l;
 51         sum[rt] = 0;
 52         return ;
 53     }
 54     int m = l + r >> 1;
 55     build(lson);
 56     build(rson);
 57     up(rt);
 58 }
 59 
 60 int clean(int L, int R, int l, int r, int rt) {
 61     int ret = 0;
 62     if (L <= l && r <= R) {
 63 //        cout << l << ' ' << r << " sum " << sum[rt] << endl;
 64         ret = sum[rt];
 65         late[rt] = 0;
 66         sum[rt] = 0;
 67         ml[rt] = l, mr[rt] = r;
 68         return ret;
 69     }
 70     int m = l + r >> 1;
 71     down(rt, l, r);
 72     if (L <= m) ret += clean(L, R, lson);
 73     if (m < R) ret += clean(L, R, rson);
 74     up(rt);
 75     return ret;
 76 }
 77 
 78 typedef pair<int, int> PII;
 79 PII insert(int L, int R, int l, int r, int rt) {
 80     PII ret = PII(-1, -1);
 81     if (L <= l && r <= R) {
 82         late[rt] = 1;
 83         sum[rt] = r - l + 1;
 84         ret = PII(ml[rt], mr[rt]);
 85         ml[rt] = mr[rt] = -1;
 86         return ret;
 87     }
 88     int m = l + r >> 1;
 89     down(rt, l, r);
 90     if (L <= m) ret = insert(L, R, lson);
 91     if (m < R) {
 92         PII tmp = insert(L, R, rson);
 93         if (ret.first == -1) ret.first = tmp.first;
 94         if (tmp.second != -1) ret.second = tmp.second;
 95     }
 96     up(rt);
 97     return ret;
 98 }
 99 
100 int getsum(int L, int R, int l, int r, int rt) {
101     if (L <= l && r <= R)  return r - l + 1 - sum[rt];
102     down(rt, l, r);
103     int m = l + r >> 1;
104     int sum = 0;
105     if (L <= m) sum += getsum(L, R, lson);
106     if (m < R) sum += getsum(L, R, rson);
107     up(rt);
108     return sum;
109 }
110 
111 int dc(int l, int r, int cnt) {
112     int mk = -1, m, p = l;
113     while (l <= r) {
114         m = l + r >> 1;
115         //cout << m << "= =" << getsum(p, m, root) << '~' << cnt << endl;
116         if (getsum(p, m, root) >= cnt) mk = m, r = m - 1;
117         else l = m + 1;
118     }
119     return mk;
120 }
121 
122 int main() {
123     int T, m;
124     int op, x, y;
125     PII tmp;
126     cin >> T;
127     while (T-- && cin >> n >> m) {
128         build(root);
129         while (m--) {
130             scanf("%d%d%d", &op, &x, &y);
131             if (op == 1) {
132                 int cnt = getsum(x, n - 1, root);
133                 y = min(y, cnt);
134                 int pos = dc(x, n - 1, y);
135                 //cout << x << '=' << pos << endl;
136                 if (~pos) {
137                     PII tmp = insert(x, pos, root);
138                     //cout << tmp.first << '~' << tmp.second << endl;
139                     if (~tmp.first) printf("%d %d
", tmp.first, tmp.second);
140                     else puts("Can not put any one.");
141                 } else {
142                     puts("Can not put any one.");
143                 }
144             } else {
145                 printf("%d
", clean(x, y, root));
146             }
147         }
148         puts("");
149     }
150     return 0;
151 }
View Code

hdu 4612:(好像是强连通分量吧,图论,队友ly过的)

  1 #pragma comment(linker,"/STACK:102400000,102400000")
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <algorithm>
  6 #include <queue>
  7 #include <cmath>
  8 #include <stack>
  9 
 10 const int N = 200005;
 11 const int E = 1000005;
 12 using namespace std;
 13 int n,m;
 14 int tot,pre[N];
 15 struct edge{
 16     int u,v,next;
 17 }e[E<<1];
 18 int dfn[N],low[N],id[N],st[N];
 19 int scc,num,top;
 20 bool vis[N];
 21 
 22 void init(){
 23     tot=0;
 24     memset(pre,-1,sizeof(pre));
 25 }
 26 
 27 void add(int u,int v){
 28     edge E={u,v,pre[u]};
 29     e[tot]=E,pre[u]=tot++;
 30 }
 31 
 32 void input(){
 33     int u,v;
 34     while(m--){
 35         scanf("%d%d",&u,&v);
 36         add(u,v),add(v,u);
 37     }
 38 }
 39 
 40 void dfs(int u,int fa){
 41     dfn[u]=low[u]=++num;
 42     vis[u]=1,st[++top]=u;
 43     int flag=1;
 44     for(int i=pre[u];i!=-1;i=e[i].next){
 45         int v=e[i].v;
 46         if(v==fa&&flag){
 47             flag=0;
 48             continue;
 49         }
 50         if(!dfn[v]){
 51             dfs(v,u);
 52             low[u]=min(low[u],low[v]);
 53         }
 54         else if(vis[v]) low[u]=min(low[u],dfn[v]);
 55     }
 56     if(low[u]==dfn[u]){
 57         scc++;
 58         while(1){
 59             int v=st[top--];
 60             id[v]=scc,vis[v]=0;
 61             if(v==u) break;
 62         }
 63     }
 64 }
 65 
 66 void tarjan(){
 67     memset(dfn,0,sizeof(dfn));
 68     memset(vis,0,sizeof(vis));
 69     scc=num=top=0;
 70     for(int i=1;i<=n;i++){
 71         if(!dfn[i]) dfs(i,-1);
 72 //        printf("id[%d]=%d
",i,id[i]);
 73     }
 74 }
 75 
 76 void build(){
 77     int nn=tot;
 78     init();
 79     for(int i=0;i<nn;i++){
 80         int u=e[i].u,v=e[i].v;
 81         if(id[u]!=id[v]) add(id[u],id[v]);
 82     }
 83 }
 84 
 85 int dis[N];
 86 int bfs(int s,int &t){
 87     queue<int> q;
 88     memset(vis,0,sizeof(vis));
 89     dis[s]=0,vis[s]=1,t=s;
 90     q.push(s);
 91     int res=0;
 92     while(!q.empty()){
 93         int u=q.front();
 94         q.pop();
 95         if(res<dis[u]){
 96             res=dis[u];
 97             t=u;
 98         }
 99         for(int i=pre[u];i!=-1;i=e[i].next){
100             int v=e[i].v;
101             if(!vis[v]){
102                 vis[v]=1;
103                 dis[v]=dis[u]+1;
104                 q.push(v);
105             }
106         }
107     }
108     return res;
109 }
110 
111 int main(){
112 //    freopen("in","r",stdin);
113     while(scanf("%d%d",&n,&m)>0){
114         if(n==0&&m==0) break;
115         init();
116         input();
117         tarjan();
118         build();
119         int u,v;
120         int res=bfs(1,u);
121         res=bfs(u,v);
122         printf("%d
",scc-1-res);
123     }
124     return 0;
125 }
View Code

  总的来说,我在比赛中打了一场酱油,做了两道水题。实际上还有几题是可以做的,例如4613,这题开始的时候就想到可以把给定的点转化成一个数列,可惜想不到怎么确定以哪个点为中心。其实这题能找到中心,搞一个KMP就可以的了。

UPD: 

Problem - 4613

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstdio>
  4 #include <cmath>
  5 #include <cstring>
  6 
  7 using namespace std;
  8 
  9 const int N = 33333;
 10 const double EPS = 1e-8;
 11 const double PI = acos(-1.0);
 12 inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
 13 struct Point {
 14     double x, y;
 15     Point() {}
 16     Point(double x, double y) : x(x), y(y) {}
 17     bool operator < (Point a) const { return sgn(x - a.x) < 0 || sgn(x - a.x) == 0 && y < a.y;}
 18     bool operator == (Point a) const { return sgn(x - a.x) == 0 && sgn(y - a.y) == 0;}
 19 } tmp[N], str[N], sub[N];
 20 
 21 template<class T> T sqr(T x) { return x * x;}
 22 
 23 int convert1(Point *s, Point *t, int n, double &u) {
 24     double sx = 0, sy = 0;
 25     for (int i = 0; i < n; i++) sx += s[i].x, sy += s[i].y;
 26     sx /= n, sy /= n;
 27     int m = 0;
 28     for (int i = 0; i < n; i++) if (sgn(sx - s[i].x) || sgn(sy - s[i].y)) s[m++] = s[i];
 29     //cout << "sx " << sx << " sy " << sy << endl;
 30     u = 0;
 31     for (int i = 0; i < m; i++) {
 32         u = max(u, sqrt(sqr(sx - s[i].x) + sqr(sy - s[i].y)));
 33         t[i].x = atan2(s[i].y - sy, s[i].x - sx);
 34     }
 35     u /= 10000;
 36     for (int i = 0; i < m; i++) t[i].y = sqrt(sqr(sx - s[i].x) + sqr(sy - s[i].y)) / u;
 37     sort(t, t + m);
 38     return m;
 39 }
 40 
 41 inline int cmp(Point a, Point b) { return a == b ? 0 : (a < b ? -1 : 1);}
 42 
 43 int minexp(Point *s, int n) {
 44     int i = 0, j = 1, k = 0, t;
 45     while (i < n && j < n && k < n) {
 46         t = cmp(s[(i + k) % n], s[(j + k) % n]);
 47         if (!t) k++;
 48         else {
 49             if (t > 0) i += k + 1;
 50             else j += k + 1;
 51             if (i == j) j++;
 52             k = 0;
 53         }
 54     }
 55     return min(i, j);
 56 }
 57 
 58 void reflect(Point *s, int n) {
 59     for (int i = 0; i < n; i++) s[i].x = -s[i].x;
 60     sort(s, s + n);
 61 }
 62 
 63 void convert2(Point *s, Point *t, int n) {
 64     s[n] = s[0];
 65     s[n].x += 2 * PI;
 66     for (int i = 0; i < n; i++) t[i].x = s[i + 1].x - s[i].x, t[i].y = s[i].y;
 67     //for (int i = 0; i < n; i++) cout << "rel " << t[i].x << ' ' << t[i].y << endl;
 68 }
 69 
 70 bool check(Point *s, Point *t, int n) {
 71     bool ret = true;
 72     int pos = minexp(t, n);
 73     rotate(t, t + pos, t + n);
 74     //for (int i = 0; i < n; i++) cout << t[i].x << '~' << t[i].y << endl;
 75     //puts("~~~~!!!!!!!!!!!!!!~~~");
 76     for (int i = 0; i < n && ret; i++) if (!(s[i] == t[i])) ret = false;
 77     return ret;
 78 }
 79 
 80 int main() {
 81     int n, m, k, T;
 82     scanf("%d", &T);
 83     while (T-- && ~scanf("%d", &n)) {
 84         for (int i = 0; i < n; i++)    scanf("%lf%lf", &str[i].x, &str[i].y);
 85         double r;
 86         int nn = convert1(str, tmp, n, r);
 87         //cout << nn << endl;
 88         convert2(tmp, str, nn);
 89         int pos = minexp(str, nn);
 90         rotate(str, str + pos, str + nn);
 91         //for (int i = 0; i < nn; i++) cout << str[i].x << ' ' << str[i].y << endl;
 92         //puts("~~~~~~~~~~~~~~~~~~~~~");
 93         scanf("%d", &m);
 94         while (m--) {
 95             scanf("%d", &k);
 96             for (int i = 0; i < k; i++) scanf("%lf%lf", &sub[i].x, &sub[i].y);
 97             if (k != n) puts("No");
 98             else {
 99                 double rr;
100                 int kk = convert1(sub, tmp, k, rr);
101                 if (kk != nn) {
102                     puts("No");
103                     continue;
104                 }
105                 convert2(tmp, sub, kk);
106                 if (check(str, sub, kk)) puts("Yes");
107                 else {
108                     reflect(tmp, kk);
109                     convert2(tmp, sub, kk);
110                     if (check(str, sub, kk)) puts("Yes");
111                     else puts("No");
112                 }
113             }
114         }
115         puts("");
116     }
117     return 0;
118 }
View Code

  题解说用KMP,不过觉得没有这样的必要,我们要的是确定一个序列的起始位置,所以我用了最小表示法来过这题。

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/2013_07_25_Lyon.html