• 2018-2019 ACM-ICPC, Asia Jiaozuo Regional Contest B,D,F


    A

    感觉是个画图题...

    当角度过小,b和a+r构不成直角三角形时,(w = b*sin(th) + (a+r) * cos(th)),否则 (w = sqrt{(a+r)^2+b^2})

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e3+10;
    const double eps = 1e-8;
    const double pi = acos(-1);
    
    int main(){
        int t;  scanf("%d",&t);
        double a,b,r,th;
        while(t--){
            scanf("%lf%lf%lf%lf",&a,&b,&r,&th);
            th = th/180*pi;
            double mp = sqrt((a+r)*(a+r)+b*b);
            double t1 = asin(b/mp);
            if(t1<=th){
                printf("%.12lf
    ",mp-r);
            }else{
                double si = sin(th),cs = cos(th);
                printf("%.12lf
    ",(a+r)*cs+b*si-r);
            }
        }
    
        return 0;
    }
    
    

    D

    模拟题

    • 思路: 找到蜂巢和连接边的规律来建图,然后跑最短路.
    #include<bits/stdc++.h>
    #define pii pair<int,int>
    using namespace std;
    const int N = 1e3+10;
    const int inf = 0x3f3f3f3f;
    char ma[N*5][N*6];
    int n,m,sp,tp;
    struct E{
        int v,nxt;
    }e[N*N*100];
    int head[N*N],tot,d[N*N];
    void init(){
        memset(head,-1,sizeof head); tot = 0;
    }
    void add(int u,int v){
        e[tot] = (E){v,head[u]}; head[u] = tot++;
        e[tot] = (E){u,head[v]}; head[v] = tot++;
    }
    int toid(int x,int y){
        return (x-1)*m+y;
    }
    int dij(){
        fill(d,d+1+n*m,inf);
        priority_queue<pii,vector<pii>,greater<pii> > que;
        d[sp] = 0;  que.push(pii(0,sp));
        while(que.size()){
            pii p = que.top();  que.pop();
            int u = p.second;
            if(d[u]<p.first)    continue;
            for(int i=head[u];~i;i=e[i].nxt){
                int v = e[i].v;
                if(d[v] > d[u]+1){
                    d[v] = d[u] + 1;
                    que.push(pii(d[v],v)); 
                }
            }
        }
        return d[tp];
    }
    int main(){
        int t;  scanf("%d",&t);
        char ch;
        while(t--){
            init();
            scanf("%d%d",&n,&m);
            getchar();
            for(int i=1;i<=n*4+3;++i){
                int idx = 1;
                do{
                    ch = getchar();
                    ma[i][idx++] = ch;
                }while(ch!='
    ');
            }
            int x,y;
            for(int i=1;i<=n;++i){
                for(int j=1;j<=m;++j){
                    if(j%2){
                        x = i*4-1,y = j*6-1; 
                        if(ma[x-1][y+3]==' '){ // 左上
                            add(toid(i,j),toid(i-1,j+1));
                        }
                        if(ma[x+1][y+3]==' '){ // 左
                            add(toid(i,j),toid(i,j+1));
                        }   
                        if(ma[x+2][y]==' '){   // 下
                            add(toid(i,j),toid(i+1,j));
                        }
                    }else{
                        x = i*4+1,y = j*6-1;
                        if(ma[x-1][y+3]==' '){ // 左
                            add(toid(i,j),toid(i,j+1));
                        }
                        if(ma[x+1][y+3]==' '){ // 左下
                            add(toid(i,j),toid(i+1,j+1));
                        }   
                        if(ma[x+2][y]==' '){   // 下
                            add(toid(i,j),toid(i+1,j));
                        }
                    }                    
                    if(ma[x][y]=='S'){sp = toid(i,j);}
                    if(ma[x][y]=='T'){tp = toid(i,j);}
                }
            }
            int ans = dij();
            if(ans!=inf)   printf("%d
    ",ans+1);
            else puts("-1");
        }
    
        return 0;
    }
    

    F

    构造题

    • 思路: a和b要优先打死一个,先算出来a和b都打死的总天数last.(只要和大于ha+hb,就一定存在一种方案组合出ha和hb),因为要字典序最小,所以构造时尽量先打a
      先打a: lower_bound算出打死a的时间pos,然后 sum[pos]-ha 为打a多的攻击力(攻击力对应了一天), 如果sum[last] - sum[pos] >= hb 说明后面可以打死b,否则要用多的攻击力那一天去打b.
      先打b: 先打b不能直接全打b,要拿盈余伤害先去打a. 具体看注释吧
    #include <bits/stdc++.h>
    #define  ll long long
    using namespace std;
    const int N = 1e6+10;
    ll sum[N];
    
    int main(){
        int n = 1e5+10;
        for(int i=1;i<n;++i){
            sum[i] = sum[i-1] + i;
        }
        int t;  scanf("%d",&t);
        while(t--){
            ll ha,hb,ta,tb;
            scanf("%lld%lld%lld%lld",&ha,&hb,&ta,&tb);
            ll last = lower_bound(sum+1,sum+n,ha+hb)-sum; // a,b都被打死
            string sa,sb;
            ll pos = lower_bound(sum+1,sum+n,ha) - sum ; // 打死a的回合
            ll los = sum[pos] - ha;                     // 盈余的伤害
            ll s1 = pos*ta + last*tb;                   // 收到的攻击
            if(sum[last] - sum[pos] >= hb){  // 后面之间可以把b打死
                for(ll i=1;i<=pos;++i)  sa += 'A';
            }else{                          // 打不死 要在前面穿插一次攻击
                for(ll i=1;i<=pos;++i){
                    if(i!=los) sa+='A';
                    else sa += 'B';
                }
            }
            for(ll i=pos+1;i<=last;++i) sa+='B';
    
            pos = lower_bound(sum+1,sum+n,hb)-sum; // 打死b的回合
            ll s2 = last*ta + pos*tb;  // 收到的伤害
            if(s1<s2){// 先a更优
                printf("%lld ",s1);
                cout << sa+'
    ';
            }else{
                los = sum[pos] - hb; // 盈余伤害
                ll lb1 = upper_bound(sum+1,sum+n,los) - sum - 1;
                ll bac = sum[last] - sum[pos]; // 后面能对a造成的伤害
                if(bac+sum[lb1]>=ha){// "AAABBBAAA"
                    for(ll i=1;i<=lb1;++i){
                        sb += 'A';
                    }
                    for(ll i=lb1+1;i<=pos;++i){
                        sb += 'B';
                    }
                }else{// AB交替 直到后面能打死A
                    ll left = ha-bac; // 还需要多少能打死A
                    for(ll i=1;i<=pos;++i){
                        if(left-i>i || left==i){ // left-i<=i 就说明后面不能构成整数天去打a了,会亏攻击力就不能去打a
                            left -= i;
                            sb += 'A';
                        }else{
                            sb += 'B';
                        }
                    }
                }
                for(ll i=pos+1;i<=last;++i){
                    sb += 'A';
                }
                printf("%lld ",s2);
                if(s2<s1) cout << sb +'
    ';
                else cout << min(sa,sb) +'
    ';
            }
        }
        return 0;
    }
    
    

    思路

  • 相关阅读:
    Python网络爬虫规则之实例
    Syncthing:同步window和linux文件
    阿里云AIoT云端一体:迎接云原生+低代码时代的到来
    低代码时代的物联网快速构建工具-YFIOs
    阿里云、华为云和腾讯云等多家物联网平台的异同
    全志 Fex文件
    le16_to_cpu
    无线充电技术简介
    AK47所向披靡,内存泄漏一网打尽
    zRAM内存压缩技术原理与应用
  • 原文地址:https://www.cnblogs.com/xxrlz/p/11649793.html
Copyright © 2020-2023  润新知