zoukankan      html  css  js  c++  java
  • 2018 ACM-ICPC World Finals

    我重写行不?

    Comma Sprinkler

    签到题,类似于BFS用两个队列维护每种单词前/后是否有逗号向前/后扩展,需要注意如果有句号挡着是不能扩展过去的,不过样例有。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 1e6 + 10;
     4 map<string, vector<int>> M;
     5 bool pre[maxn], suc[maxn];
     6 bool st[maxn], ed[maxn];
     7 queue<string> QP, QS;
     8 set<string> SP, SS;
     9 string str[maxn];
    10 
    11 int main() {
    12     string s;
    13     getline(cin, s);
    14     int l = s.length(), p = 1;
    15     st[p] = true;
    16     for(int i = 0; i < l; ++i) {
    17         if(s[i] == ',') {
    18             suc[p] = pre[p + 1] = true;
    19             ++p, ++i;
    20         }
    21         else if(s[i] == '.') {
    22             ed[p] = st[p + 1] = true;
    23             ++p, ++i;
    24         }
    25         else if(s[i] == ' ') ++p;
    26         else str[p].push_back(s[i]);
    27     }
    28     for(int i = 1; i < p; ++i) M[str[i]].push_back(i);
    29     for(int i = 1; i < p; ++i) {
    30         if(pre[i] && SP.find(str[i]) == SP.end()) SP.insert(str[i]), QP.push(str[i]);
    31         if(suc[i] && SS.find(str[i]) == SS.end()) SS.insert(str[i]), QS.push(str[i]);
    32     }
    33     while(!QP.empty() || !QS.empty()) {
    34         while(!QP.empty()) {
    35             string cur = QP.front(); QP.pop();
    36             vector<int>& pos = M[cur];
    37             for(int i = 0; i < pos.size(); ++i) {
    38                 int x = pos[i];
    39                 if(!st[x]) pre[x] = true;
    40                 if(x - 1 > 0 && !ed[x - 1] && SS.find(str[x - 1]) == SS.end()) suc[x - 1] = true, SS.insert(str[x - 1]), QS.push(str[x - 1]);
    41             }
    42         }
    43         while(!QS.empty()) {
    44             string cur = QS.front(); QS.pop();
    45             vector<int>& pos = M[cur];
    46             for(int i = 0; i < pos.size(); ++i) {
    47                 int x = pos[i];
    48                 if(!ed[x]) suc[x] = true;
    49                 if(x + 1 < p && !st[x + 1] && SP.find(str[x + 1]) == SP.end()) pre[x + 1] = true, SP.insert(str[x + 1]), QP.push(str[x + 1]);
    50             }
    51         }
    52     }
    53     for(int i = 1; i < p; ++i) {
    54         cout << str[i];
    55         if(ed[i]) cout << '.';
    56         else if(suc[i]) cout << ',';
    57         if(i < p - 1) cout << ' ';
    58         else cout << endl;
    59     }
    60     return 0;
    61 }
    Aguin

    Wireless is the New Fiber

    题意是构造一棵树使得树上度与原图度不相等的节点尽量少。

    考虑一个贪心,按度从小到大排序后,对于每个度大于1的点,在上面挂叶子直到度为1,那么这个连通块也看成一个叶子。

    如果某个时刻叶子不够了,那么就舍弃度最大的点,把它当做叶子挂上去。

    最后如果还有叶子没用完,若剩两个叶子正好拼成一棵树,否则舍弃一个叶子作为根把别的挂上去。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 1e4 + 10;
     4 typedef pair<int, int> pii;
     5 int deg[maxn], id[maxn];
     6 vector<pii> ans2;
     7 vector<int> one;
     8 
     9 bool cmp(int i, int j) {
    10     return deg[i] < deg[j];
    11 }
    12 
    13 int main() {
    14     int n, m;
    15     scanf("%d %d", &n, &m);
    16     int ans1 = n;
    17     for(int i = 1; i <= m; ++i) {
    18         int u, v;
    19         scanf("%d %d", &u, &v);
    20         ++u, ++v;
    21         deg[u] += 1, deg[v] += 1;
    22     }
    23     for(int i = 1; i <= n; ++i) id[i] = i;
    24     sort(id + 1, id + 1 + n, cmp);
    25     int st = 1, ed = n;
    26     while(st <= n && deg[id[st]] == 1) {
    27         one.push_back(id[st]);
    28         ++st;
    29     }
    30     for(int i = st; i <= ed; ++i) {
    31         int x = id[i];
    32         while(deg[x] > 1 && !one.empty()) {
    33             int y = one.back();
    34             one.pop_back();
    35             deg[x]--, deg[y]--;
    36             ans1--;
    37             ans2.emplace_back(pii(x, y));
    38         }
    39         while(deg[x] > 1 && ed > i) {
    40             int y = id[ed];
    41             deg[x]--, deg[y]--;
    42             ans2.emplace_back(pii(x, y));
    43             ed--;
    44         }
    45         if(deg[x] == 1) one.push_back(x);
    46     }
    47     if(one.size() > 1) {
    48         for(int i = 1; i < one.size(); ++i)
    49             ans2.emplace_back(pii(one[0], one[i]));
    50         ans1 -= one.size() - 1;
    51         if(one.size() == 2) ans1--;
    52     }
    53     printf("%d
    %d %d
    ", ans1, n, int(ans2.size()));
    54     for(int i = 0; i < ans2.size(); ++i) printf("%d %d
    ", ans2[i].first - 1, ans2[i].second - 1);
    55     return 0;
    56 }
    Aguin

    Go with the Flow

    暴力枚举长度,然后算每个空格的最长链,时限卡的有点紧。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 3e5 + 10;
     4 int pre[maxn], cur[maxn];
     5 vector<int> v;
     6 
     7 int main() {
     8     int n, wid = -1, ans = 0, sum = 0, M = 0;
     9     scanf("%d", &n);
    10     for(int i = 1; i <= n; ++i) {
    11         char s[111];
    12         scanf("%s", s);
    13         int l = strlen(s);
    14         v.push_back(l);
    15         M = max(M, l);
    16         sum += l;
    17     }
    18     for(int W = M; W <= sum + n - 1; ++W) {
    19         int tmp = 0;
    20         vector<int> P, C;
    21         int pos = 0, fir = 1, ok = 0;
    22         for(int i = 0; i < v.size(); ++i) {
    23             if(!fir && pos + 1 + v[i] > W) {
    24                 for(int j = 0; j < P.size(); ++j) pre[P[j]] = 0;
    25                 for(int j = 0; j < C.size(); ++j) pre[C[j]] = cur[C[j]], cur[C[j]] = 0;
    26                 P = C, C.clear();
    27                 fir = 1;
    28                 pos = 0;
    29             }
    30             if(fir) {
    31                 pos += v[i];
    32                 fir = 0;
    33             }
    34             else {
    35                 pos += 1;
    36                 int r = 1;
    37                 if(pos > 1) r = max(r, pre[pos - 1] + 1);
    38                 r = max(r, pre[pos] + 1);
    39                 if(pos < W) r = max(r, pre[pos + 1] + 1);
    40                 cur[pos] = r, C.push_back(pos);
    41                 pos += v[i];
    42                 tmp = max(tmp, r);
    43             }
    44             if(pos == W) ok = 1;
    45         }
    46         if(ok && tmp > ans) ans = tmp, wid = W;
    47         for(int j = 0; j < P.size(); ++j) pre[P[j]] = 0;
    48         for(int j = 0; j < C.size(); ++j) cur[C[j]] = 0;
    49     }
    50     printf("%d %d
    ", wid, ans);
    51     return 0;
    52 }
    Aguin

    Catch the Plane

    将线路按出发时间排序,倒着dp。

    对于每条线路(a, b, s, t, p),记a点在严格大于s时刻的最优值为ta,b点在严格大于t的最优值为tb。

    每个时刻的决策有两种,若选择乘坐,则以p的概率转移到tb,1 - p概率继承ta;若不乘坐则直接继承ta。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 typedef pair<ll, int> pr;
     5 const int maxn = 1e6 + 10;
     6 map<ll, double> :: iterator ita, itb;
     7 map<ll, double> f[maxn];
     8 int a[maxn], b[maxn];
     9 ll s[maxn], t[maxn];
    10 double p[maxn];
    11 vector<pr> v;
    12 
    13 int main() {
    14     ll k;
    15     int m, n;
    16     scanf("%d %d %lld", &m, &n, &k);
    17     for(int i = 1; i <= m; ++i) {
    18         scanf("%d %d %lld %lld %lf", a + i, b + i, s + i, t + i, p + i);
    19         v.emplace_back(pr(s[i], i));
    20     }
    21     sort(v.begin(), v.end());
    22     f[1][k + 1] = 1;
    23     for(int i = int(v.size()) - 1; i >= 0; --i) {
    24         int e = v[i].second, ai = a[e], bi = b[e];
    25         ll si = v[i].first, ti = t[e];
    26         double pi = p[e];
    27         ita = f[ai].upper_bound(si);
    28         itb = f[bi].upper_bound(ti);
    29         double ta = 0, tb = 0;
    30         if(ita != f[ai].end()) ta = (*ita).second;
    31         if(itb != f[bi].end()) tb = (*itb).second;
    32         f[ai][si] = max(f[ai][si], max(ta, pi * tb + (1 - pi) * ta));
    33     }
    34     printf("%.8f
    ", (*f[0].begin()).second);
    35     return 0;
    36 }
    Aguin

    Single Cut of Failure

    注意到取两条对角线是一定可以切到所有线段的,因此答案最大为2,只需考虑1的情况。

    将线段转变为环上的区间,相当于找两个端点切开所有区间。

    枚举其中一个位置,另一个双指针单调移动。

    最后将答案投回矩形上的位置。

    注意不能重点,不能取角点。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 1e6 + 10;
     4 typedef pair<int, int> pii;
     5 bool vis[maxn];
     6 vector<pii> v;
     7 int n, w, h;
     8 
     9 inline int cal(int x, int y) {
    10     if(x == 0) return y;
    11     if(y == h) return h + x;
    12     if(x == w) return 2 * h + w - y;
    13     return 2 * (h + w) - x;
    14 }
    15 
    16 inline void get(double t, double& x, double& y) {
    17     if(t <= h) x = 0, y = t;
    18     else if(t <= h + w) x = t - h, y = h;
    19     else if(t <= 2 * h + w) x = w, y = 2 * h + w - t;
    20     else x = 2 * (h + w) - t, y = 0;
    21 }
    22 
    23 int main() {
    24     scanf("%d %d %d", &n, &w, &h);
    25     for(int i = 0; i < n; ++i) {
    26         int X1, Y1, X2, Y2;
    27         scanf("%d %d %d %d", &X1, &Y1, &X2, &Y2);
    28         v.push_back(pii(cal(X1, Y1), i));
    29         v.push_back(pii(cal(X2, Y2), i));
    30     }
    31     sort(v.begin(), v.end());
    32     int sz = int(v.size()), p = 0, cnt = 0, one = 0;
    33     for(int i = 0; i < sz; ++i) {
    34         if(p == i) vis[v[i].second] = true, ++p, ++cnt;
    35         while(!vis[v[p].second]) vis[v[p].second] = true, p = (p + 1) % sz, ++cnt;
    36         if(cnt == n) {
    37             double ax1, ay1, ax2, ay2;
    38             get(v[i].first - 0.5, ax1, ay1);
    39             get(v[p].first - 0.5, ax2, ay2);
    40             printf("1
    %.8f %.8f %.8f %.8f
    ", ax1, ay1, ax2, ay2);
    41             one = 1; break;
    42         }
    43         vis[v[i].second] = false, --cnt;
    44     }
    45     if(!one) printf("2
    0.5 0 %.8f %.8f
    0 %.8f %.8f %.8f
    ", w - 0.5, 1.0 * h, h - 0.5, 1.0 * w, 0.5);
    46     return 0;
    47 }
    Aguin

    Triangles

    考虑统计每个▽,将图上下翻转后再做一次即为全部三角形。

    按从右往左从上往下的顺序扫描每一个方向斜线上的点,考虑这个点作为▽下顶点的贡献。

    假设这个点往左上,右上延伸的最大长度分别为UL和UR,那么相当于询问在向上min(UL, UR)的范围内有多少横线长度大于等于到枚举顶点的距离。

    这个直观感觉不太好统计,那么反过来考虑每一条横线对于哪些▽下顶点是有效的。

    假设在某点处向右的最大距离为R,那么这条横线对于它下方R范围内的顶点都是可以作为三角形▽上边的。

    在扫描的过程中顺便维护好UL,UR和R,用一个树状数组维护这个斜线上横线的贡献,即在扫描到的时候+1,在下方R处加一个删除标记,扫到的时候删掉。

    枚举下顶点的时候,只要在树状数组上询问一下min(UL, UR)范围内的有效横线数目。

    时限很紧,不仅要比较好的读入还要常数小。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 
     5 int f[66666];
     6 inline int lowbit(int s) {
     7     return s & (-s);
     8 }
     9 inline void modify(int i, int x, int n) {
    10     while (i <= n) f[i] += x, i += lowbit(i);
    11 }
    12 inline int query(int i) {
    13     int ret = 0;
    14     while (i > 0) ret += f[i], i -= lowbit(i);
    15     return ret;
    16 }
    17 vector<int> del[66666];
    18 
    19 int main() {
    20     ios_base :: sync_with_stdio(0);
    21     cin.tie(0);
    22     int r, c;
    23     cin >> r >> c;
    24     r = 2 * r - 1, c = 2 * c - 1;
    25     vector<string> s(r);
    26     getline(cin, s[0]);
    27     for(int i = 0; i < r; ++i) {
    28         getline(cin, s[i]);
    29         while(s[i].length() < c) s[i].push_back(' ');
    30     }
    31     ll ans = 0;
    32     for(int rot = 0; rot < 2; ++rot) {
    33         vector< vector<int> > R(r, vector<int>(c, 0));
    34         vector< vector<int> > UL(r, vector<int>(c, 0));
    35         vector< vector<int> > UR(r, vector<int>(c, 0));
    36         for(int j = c - 1; j >= 0; --j) {
    37             if(s[0][j] != 'x') continue;
    38             int maxi = min((r - 1) / 2, (c - 1 - j) / 2) + 1;
    39             for(int ii = 0, jj = j; ii < r && jj < c; ii += 2, jj += 2) {
    40                 if(jj + 2 < c && s[ii][jj + 2] != ' ') R[ii][jj] = R[ii][jj + 4] + 1;
    41                 if(ii >= 2 && jj >= 2 && s[ii - 1][jj - 1] != ' ') UL[ii][jj] = UL[ii - 2][jj - 2] + 1;
    42                 if(ii >= 2 && jj + 2 < c && s[ii - 1][jj + 1] != ' ') UR[ii][jj] = UR[ii - 2][jj + 2] + 1;
    43                 ans += query(ii / 2 + 1) - query(ii / 2 - min(UL[ii][jj], UR[ii][jj]));
    44                 if(R[ii][jj]) {
    45                     modify(ii / 2 + 1, 1, maxi);
    46                     del[min(ii / 2 + 1 + R[ii][jj], maxi)].push_back(ii / 2 + 1);
    47                 }
    48                 for(auto x: del[ii / 2 + 1]) modify(x, -1, maxi);
    49                 del[ii / 2 + 1].clear();
    50             }
    51         }
    52         for(int i = 1; i < r; i++) {
    53             if(s[i][0] != 'x') continue;
    54             int maxj = min((r - 1 - i) / 2, (c - 1) / 2) + 1;
    55             for(int ii = i, jj = 0; ii < r && jj < c; ii += 2, jj += 2) {
    56                 if(jj + 2 < c && s[ii][jj + 2] != ' ') R[ii][jj] = R[ii][jj + 4] + 1;
    57                 if(ii >= 2 && jj >= 2 && s[ii - 1][jj - 1] != ' ') UL[ii][jj] = UL[ii - 2][jj - 2] + 1;
    58                 if(ii >= 2 && jj + 2 < c && s[ii - 1][jj + 1] != ' ') UR[ii][jj] = UR[ii - 2][jj + 2] + 1;
    59                 ans += query(jj / 2 + 1) - query(jj / 2 - min(UL[ii][jj], UR[ii][jj]));
    60                 if(R[ii][jj]) {
    61                     modify(jj / 2 + 1, 1, maxj);
    62                     del[min(jj / 2 + 1 + R[ii][jj], maxj)].push_back(jj / 2 + 1);
    63                 }
    64                 for(auto x: del[jj / 2 + 1]) modify(x, -1, maxj);
    65                 del[jj / 2 + 1].clear();
    66             }
    67         }
    68         reverse(s.begin(), s.end());
    69     }
    70     cout << ans << endl;
    71     return 0;
    72 }
    Aguin

    Panda Preserve

    由于圆半径一致,对于多边形内的每一个点,总是最先被距离自己最近的顶点覆盖到。

    也即是说,每个顶点要覆盖到以自己为最近顶点的区域,即维诺图,又称泰森多边形,只要枚举顶点做中垂线即可得到这个凸多边形。

    我们只关心这个凸多边形和原多边形交的部分,关键点只有两种情况:凸多边形顶点在原多边形内部;两多边形交点。

    暴力求出关键点算距离取最大值即可。

    需要抄的板子大概是一个中垂线,半平面交,点多边形位置关系。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 typedef double db;
      5 const db eps=1e-6;
      6 int sign(db k){
      7     if (k>eps) return 1; else if (k<-eps) return -1; return 0;
      8 }
      9 int cmp(db k1,db k2){return sign(k1-k2);}
     10 int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}// k3 在 [k1,k2] 内
     11 struct point{
     12     db x,y;
     13     point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
     14     point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
     15     point operator * (db k1) const{return (point){x*k1,y*k1};}
     16     point operator / (db k1) const{return (point){x/k1,y/k1};}
     17     int operator == (const point &k1) const{return cmp(x,k1.x)==0&&cmp(y,k1.y)==0;}
     18     // 逆时针旋转
     19     point turn90(){return (point){-y,x};}
     20     bool operator < (const point k1) const{
     21         int a=cmp(x,k1.x);
     22         if (a==-1) return 1; else if (a==1) return 0; else return cmp(y,k1.y)==-1;
     23     }
     24     db abs(){return sqrt(x*x+y*y);}
     25     int getP() const{return sign(y)==1||(sign(y)==0&&sign(x)==-1);}
     26 };
     27 int inmid(point k1,point k2,point k3){return inmid(k1.x,k2.x,k3.x)&&inmid(k1.y,k2.y,k3.y);}
     28 db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
     29 db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;}
     30 // -pi -> pi
     31 int compareangle (point k1,point k2){
     32     return k1.getP()<k2.getP()||(k1.getP()==k2.getP()&&sign(cross(k1,k2))>0);
     33 }
     34 point getLL(point k1,point k2,point k3,point k4){
     35     db w1=cross(k1-k3,k4-k3),w2=cross(k4-k3,k2-k3); return (k1*w2+k2*w1)/(w1+w2);
     36 }
     37 int intersect(db l1,db r1,db l2,db r2){
     38     if (l1>r1) swap(l1,r1); if (l2>r2) swap(l2,r2); return cmp(r1,l2)!=-1&&cmp(r2,l1)!=-1;
     39 }
     40 int checkSS(point k1,point k2,point k3,point k4){
     41     return intersect(k1.x,k2.x,k3.x,k4.x)&&intersect(k1.y,k2.y,k3.y,k4.y)&&
     42            sign(cross(k3-k1,k4-k1))*sign(cross(k3-k2,k4-k2))<=0&&
     43            sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<=0;
     44 }
     45 int onS(point k1,point k2,point q){return inmid(k1,k2,q)&&sign(cross(k1-q,k2-k1))==0;}
     46 struct line{
     47     // p[0]->p[1]
     48     point p[2];
     49     line(point k1,point k2){p[0]=k1; p[1]=k2;}
     50     point& operator [] (int k){return p[k];}
     51     int include(point k){return sign(cross(p[1]-p[0],k-p[0]))>0;}
     52     point dir(){return p[1]-p[0];}
     53 };
     54 point getLL(line k1,line k2){return getLL(k1[0],k1[1],k2[0],k2[1]);}
     55 int parallel(line k1,line k2){return sign(cross(k1.dir(),k2.dir()))==0;}
     56 int sameDir(line k1,line k2){return parallel(k1,k2)&&sign(dot(k1.dir(),k2.dir()))==1;}
     57 int operator < (line k1,line k2){
     58     if (sameDir(k1,k2)) return k2.include(k1[0]);
     59     return compareangle(k1.dir(),k2.dir());
     60 }
     61 int checkpos(line k1,line k2,line k3){return k3.include(getLL(k1,k2));}
     62 vector<line> getHL(vector<line> &L){ // 求半平面交 , 半平面是逆时针方向 , 输出按照逆时针
     63     sort(L.begin(),L.end()); deque<line> q;
     64     for (int i=0;i<(int)L.size();i++){
     65         if (i&&sameDir(L[i],L[i-1])) continue;
     66         while (q.size()>1&&!checkpos(q[q.size()-2],q[q.size()-1],L[i])) q.pop_back();
     67         while (q.size()>1&&!checkpos(q[1],q[0],L[i])) q.pop_front();
     68         q.push_back(L[i]);
     69     }
     70     while (q.size()>2&&!checkpos(q[q.size()-2],q[q.size()-1],q[0])) q.pop_back();
     71     while (q.size()>2&&!checkpos(q[1],q[0],q[q.size()-1])) q.pop_front();
     72     vector<line>ans; for (int i=0;i<q.size();i++) ans.push_back(q[i]);
     73     return ans;
     74 }
     75 int contain(vector<point>A,point q){ // 2 内部 1 边界 0 外部
     76     int pd=0; A.push_back(A[0]);
     77     for (int i=1;i<A.size();i++){
     78         point u=A[i-1],v=A[i];
     79         if (onS(u,v,q)) return 1; if (cmp(u.y,v.y)>0) swap(u,v);
     80         if (cmp(u.y,q.y)>=0||cmp(v.y,q.y)<0) continue;
     81         if (sign(cross(u-v,q-v))<0) pd^=1;
     82     }
     83     return pd<<1;
     84 }
     85 
     86 int main() {
     87     int n;
     88     double ans = 0;
     89     scanf("%d", &n);
     90     vector<point> p = vector<point>(n);
     91     for(int i = 0; i < n; ++i) scanf("%lf %lf", &p[i].x, &p[i].y);
     92     for(int i = 0; i < n; ++i) {
     93         vector<line> L;
     94         L.emplace_back(line{point{-20000, -20000}, point{20000, -20000}});
     95         L.emplace_back(line{point{20000, -20000}, point{20000, 20000}});
     96         L.emplace_back(line{point{20000, 20000}, point{-20000, 20000}});
     97         L.emplace_back(line{point{-20000, 20000}, point{-20000, -20000}});
     98         for(int j = 0; j < n; ++j) {
     99             if(i == j) continue;
    100             point mid = (p[i] + p[j]) / 2;
    101             L.emplace_back(line{mid, (p[j] - mid).turn90() + mid});
    102         }
    103         L = getHL(L);
    104         int sz = int(L.size());
    105         if(sz > 2) {
    106             vector<point> v = vector<point>(sz);
    107             for(int j = 0; j < sz; ++j) {
    108                 v[j] = getLL(L[j], L[(j + 1) % sz]);
    109                 if(contain(p, v[j])) ans = max(ans, (p[i] - v[j]).abs());
    110             }
    111             for(int j = 0; j < sz; ++j) {
    112                 line l1 = line{v[j], v[(j + 1) % sz]};
    113                 for(int k = 0; k < n; ++k) {
    114                     line l2 = line{p[k], p[(k + 1) % n]};
    115                     if(checkSS(v[j], v[(j + 1) % sz], p[k], p[(k + 1) % n])) {
    116                         point u = getLL(l1, l2);
    117                         ans = max(ans, (p[i] - u).abs());
    118                     }
    119                 }
    120             }
    121         }
    122     }
    123     printf("%.8f
    ", ans);
    124     return 0;
    125 }
    Aguin

    Gem Island

    考虑分批发放,每次给选中的人一批人各发一个宝石,例如第一步可以看成是给n个人各发一个宝石,第二步则在n个人中选择一个子集,第三步在第二步选中的人中再选择子集……

    用f[i][j][k]表示第i批,已经发了j个宝石,目前选中的人集合大小为k的所有方案前r个人的宝石和,g[i][j][k]表示方案数。

    转移考虑枚举k个人的子集l,方案数只要乘上C(k, l),贡献增加是方案数乘min(r, l)。

    最后用插板法除个总数就是期望。

    第一维空间可以滚动数组,n4敢水敢过。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 double c[1005][1005], f[2][505][505], g[2][505][505];
     4 
     5 int main() {
     6     for(int i = 0; i < 1005; ++i) c[i][0] = c[i][i] = 1;
     7     for(int i = 2; i < 1005; ++i)
     8         for(int j = 1; j < i; ++j)
     9             c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
    10     double ans = 0;
    11     int n, d, r, o = 0;
    12     scanf("%d %d %d", &n, &d, &r);
    13     f[0][0][n] = r, g[0][0][n] = 1;
    14     for(int i = 2; i <= d + 1; ++i) {
    15         o ^= 1;
    16         memset(f[o], 0, sizeof(f[o]));
    17         memset(g[o], 0, sizeof(g[o]));
    18         for(int j = 0; j <= d; ++j) {
    19             for(int k = 1; k <= n; ++k) {
    20                 if(g[o ^ 1][j][k] == 0) continue;
    21                 for(int l = 1; l <= k; ++l) {
    22                     if(j + l > d) break;
    23                     g[o][j + l][l] += g[o ^ 1][j][k] * c[k][l];
    24                     f[o][j + l][l] += f[o ^ 1][j][k] * c[k][l] + g[o ^ 1][j][k] * c[k][l] * min(l, r);
    25                 }
    26             }
    27         }
    28         for(int k = 1; k <= n; ++k) ans += f[o][d][k];
    29     }
    30     printf("%.8f
    ", ans / c[d + n - 1][d]);
    31     return 0;
    32 }
    Aguin

    Getting a Jump on Crime

    枚举格子对判断是否可达,先根据距离和高度差可以求出运动时间,注意判无解的情况,然后可以得到轨迹方程。

    然后算这条轨迹在水平面投影的直线,计算投影和每条横线、纵线的交点位置,如果不在4个格子的角落则只要判两边,否则判四周。

    最后随便bfs或者floyd一下。

    无脑抄板的话只需要一个线段交的样子。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 const double g = 9.80665;
      4 typedef pair<int, int> pii;
      5 vector<pii> G[22][22];
      6 int H[22][22];
      7 
      8 typedef double db;
      9 const db eps=1e-8;
     10 int sign(db k){
     11     if (k>eps) return 1; else if (k<-eps) return -1; return 0;
     12 }
     13 int cmp(db k1,db k2){return sign(k1-k2);}
     14 struct point{
     15     db x,y;
     16     point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
     17     point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
     18     point operator * (db k1) const{return (point){x*k1,y*k1};}
     19     point operator / (db k1) const{return (point){x/k1,y/k1};}
     20     int operator == (const point &k1) const{return cmp(x,k1.x)==0&&cmp(y,k1.y)==0;}
     21     bool operator < (const point k1) const{
     22         int a=cmp(x,k1.x);
     23         if (a==-1) return 1; else if (a==1) return 0; else return cmp(y,k1.y)==-1;
     24     }
     25     db abs(){return sqrt(x*x+y*y);}
     26 };
     27 db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
     28 point getLL(point k1,point k2,point k3,point k4){
     29     db w1=cross(k1-k3,k4-k3),w2=cross(k4-k3,k2-k3); return (k1*w2+k2*w1)/(w1+w2);
     30 }
     31 int intersect(db l1,db r1,db l2,db r2){
     32     if (l1>r1) swap(l1,r1); if (l2>r2) swap(l2,r2); return cmp(r1,l2)!=-1&&cmp(r2,l1)!=-1;
     33 }
     34 int checkSS(point k1,point k2,point k3,point k4){
     35     return intersect(k1.x,k2.x,k3.x,k4.x)&&intersect(k1.y,k2.y,k3.y,k4.y)&&
     36            sign(cross(k3-k1,k4-k1))*sign(cross(k3-k2,k4-k2))<=0&&
     37            sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<=0;
     38 }
     39 
     40 inline double sq(double x) {return x * x;}
     41 inline double cal(double a, double b, double c, double x) {
     42     return a * x * x + b * x + c;
     43 }
     44 int ans[22][22];
     45 int main() {
     46     int dx, dy, w, v, lx, ly;
     47     scanf("%d %d %d %d %d %d", &dx, &dy, &w, &v, &lx, &ly);
     48     for(int i = 1; i <= dy; ++i)
     49         for(int j = 1; j <= dx; ++j)
     50             scanf("%d", &H[i][j]);
     51     for(int i = 1; i <= dy; ++i) {
     52         for(int j = 1; j <= dx; ++j) {
     53             point p1 = point{(i - 0.5) * w, (j - 0.5) * w};
     54             for(int p = 1; p <= dy; ++p) {
     55                 for(int q = 1; q <= dx; ++q) {
     56                     if(i == p && j == q) continue;
     57                     point p2 = point{(p - 0.5) * w, (q - 0.5) * w};
     58                     double h = H[p][q] - H[i][j];
     59                     double d = (p1 - p2).abs();
     60                     if(sq(v) < g * h || sq(g * h - sq(v)) < sq(g) * (sq(d) + sq(h))) continue;
     61                     double t = sqrt((sq(v) - g * h + sqrt(sq(g * h - sq(v)) - sq(g) * (sq(d) + sq(h)))) / (sq(g) / 2));
     62                     double cost = d / t / v;
     63                     double a = -0.5 * g / sq(v * cost), b = sqrt(1 - sq(cost)) / cost, c = H[i][j];
     64                     int ok = 1;
     65                     for(int o = 1; o < dy; ++o) {
     66                         point p3 = point{1.0 * w * o, 0.0};
     67                         point p4 = point{1.0 * w * o, 1.0 * w * dx};
     68                         if(checkSS(p1, p2, p3, p4)) {
     69                             point its = getLL(p1, p2, p3, p4);
     70                             double dis = (its - p3).abs() / w;
     71                             double ht = cal(a, b, c, (its - p1).abs());
     72                             if(abs(int(dis) - dis) < eps) {
     73                                 int x1 = int(dis), x2 = x1 + 1;
     74                                 if(ht < H[o][x1] || ht < H[o + 1][x1]) ok = 0;
     75                                 if(ht < H[o][x2] || ht < H[o + 1][x2]) ok = 0;
     76                             }
     77                             else if(abs(int(dis) + 1 - dis) < eps) {
     78                                 int x1 = int(dis) + 1, x2 = x1 + 1;
     79                                 if(ht < H[o][x1] || ht < H[o + 1][x1]) ok = 0;
     80                                 if(ht < H[o][x2] || ht < H[o + 1][x2]) ok = 0;
     81                             }
     82                             else {
     83                                 int x = int(dis) + 1;
     84                                 if(ht < H[o][x] || ht < H[o + 1][x]) ok = 0;
     85                             }
     86                         }
     87                     }
     88                     for(int o = 1; o < dx; ++o) {
     89                         point p3 = point{0.0, 1.0 * w * o};
     90                         point p4 = point{1.0 * w * dy, 1.0 * w * o};
     91                         if(checkSS(p1, p2, p3, p4)) {
     92                             point its = getLL(p1, p2, p3, p4);
     93                             double dis = (its - p3).abs() / w;
     94                             double ht = cal(a, b, c, (its - p1).abs());
     95                             if(abs(int(dis) - dis) < eps) {
     96                                 int x1 = int(dis), x2 = x1 + 1;
     97                                 if(ht < H[x1][o] || ht < H[x1][o + 1]) ok = 0;
     98                                 if(ht < H[x2][o] || ht < H[x2][o + 1]) ok = 0;
     99                             }
    100                             else if(abs(int(dis) + 1 - dis) < eps) {
    101                                 int x1 = int(dis) + 1, x2 = x1 + 1;
    102                                 if(ht < H[x1][o] || ht < H[x1][o + 1]) ok = 0;
    103                                 if(ht < H[x2][o] || ht < H[x2][o + 1]) ok = 0;
    104                             }
    105                             else {
    106                                 int x = int(dis) + 1;
    107                                 if(ht < H[x][o] || ht < H[x][o + 1]) ok = 0;
    108                             }
    109                         }
    110                     }
    111                     if(ok) G[i][j].emplace_back(pii(p, q));
    112                 }
    113             }
    114         }
    115     }
    116     memset(ans, -1, sizeof(ans));
    117     queue<pii> q;
    118     q.push(pii(ly, lx));
    119     ans[ly][lx] = 0;
    120     while(!q.empty()) {
    121         pii tmp = q.front(); q.pop();
    122         int x = tmp.first, y = tmp.second;
    123         for(int i = 0; i < G[x][y].size(); ++i) {
    124             pii nxt = G[x][y][i];
    125             int xx = nxt.first, yy = nxt.second;
    126             if(ans[xx][yy] == -1) {
    127                 ans[xx][yy] = ans[x][y] + 1;
    128                 q.push(nxt);
    129             }
    130         }
    131     }
    132     for(int i = 1; i <= dy; ++i) {
    133         for(int j = 1; j <= dx; ++j) {
    134             if(ans[i][j] == -1) putchar('X');
    135             else printf("%d", ans[i][j]);
    136             printf("%c", j == dx ? '
    ' : ' ');
    137         }
    138     }
    139     return 0;
    140 }
    Aguin

    最后两题不看了西西

  • 相关阅读:
    fiddler 抓取 安卓模拟器 https包
    heidiSQL使用简介
    weblogic重启脚本
    svn命令在linux下的使用
    LVS之NAT和DR服务脚本
    LVS之NAT模型、DR模型配置和持久连接
    apache ab压力测试报错apr_socket_recv
    LVS负载均衡模型及算法概述
    Orcale11g单机安装与卸载
    IPC相关的命令
  • 原文地址:https://www.cnblogs.com/Aguin/p/8883601.html
Copyright © 2011-2022 走看看