• 学大伟业Day1解题报告


    学大伟业Day1解题报告

    张炳琪

    一.   时间分配

    T1:30分钟  T2: 60分钟  T3:100分钟

    二.答题情况及错因

    T1:100         T2:55             T3:0

    T1:刚开始想枚举的方法,后来发现时间复杂度好像是对的,就那样写了

    T2:对数据范围判断不准确,刚开始打算用set盼重怕炸空间,后来又改成了数组结果改错了

    T3:看到题目知道是树形dp,然后推了一个多小时的转移方程,写了一张多纸,没推出来

    在有大题不会的情况下,要先保证能拿到的分拿到,不然做不出来大题就很吃亏

    三.题目解析

    T1:

    暴力维护两个点的链接可以发现在两个英文字母形成的区间里面至多每个字母只能与他形成一个交叉点

    那么我们从右到左枚举每个字母出现的区间直到发现与之交叉的或者右边界超出了控制范围(这个也可以二分,但是实际复杂度并不好)

    T2:

    增加了限制条件的最短路   

    首先数据范围是吓唬人的,两千条边用 100000000限速器没有任何用处 

    5000 * 2000 的visited数组用来判重

    然后spfa 中间两种转移,队列中记录下当前用了多少加速器 ,一种转移耗费加速器  一种不耗费

    T3:

    四.代码

    T1:

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #define MAXN 101000
    using namespace std;
    
    int ln[27][MAXN];
    int rn[27][MAXN];
    int top[27];
    char s[MAXN];
    int ans = 0;
    
    int main() {
        freopen("cross.in","r",stdin);freopen("cross.out","w",stdout);
        scanf("%s",s + 1);
        int len = strlen(s + 1);
        for(int i = 1; i <= len; i++) {
            s[i] = s[i] - 'a' + 1;
            if(ln[s[i]][top[s[i]]] == 0) {
                ln[s[i]][top[s[i]]] = i;
            } else if(rn[s[i]][top[s[i]]] == 0) {
                rn[s[i]][top[s[i]]] = i;
                for(int j = 1; j <= 26; j++) {
                    if(j == s[i])continue;
                    for(int k = top[j] - 1; k >= 0; k--) {
                        if(ln[j][k] < ln[s[i]][top[s[i]]] && rn[j][k] > ln[s[i]][top[s[i]]]) {
                            ans++;
                            break;
                        }
                        if(rn[j][k] < ln[s[i]][top[s[i]]])
                            break;
                    }
                }
                top[s[i]]++;
            }
        }
        printf("%d",ans);
        return 0;
    }
    #include<queue>
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #define MAXN 5010
    using namespace std;
    
    struct Edge {
        int vj;
        int wei;
        int nxt;
    } edge1[MAXN * 4],edge2[MAXN * 4];
    int now1,now2;
    int head1[MAXN],head2[MAXN];
    
    struct Note {
        int now;
        int used;
    } be;
    
    queue<Note>q;
    
    void push1(int vi,int vj,int wei) {
        now1++;
        edge1[now1].vj = vj;
        edge1[now1].wei = wei;
        edge1[now1].nxt = head1[vi];
        head1[vi] = now1;
    }
    void push2(int vi,int vj,int wei) {
        now2++;
        edge2[now2].vj = vj;
        edge2[now2].wei = wei;
        edge2[now2].nxt = head2[vi];
        head2[vi] = now2;
    }
    int read() {
        int nm = 0;
        char c = getchar();
        while(c < '0' || c > '9')c = getchar();
        while(c >= '0' && c <= '9') {
            nm *= 10;
            nm += c -'0';
            c = getchar();
        }
        return nm;
    }
    
    int n,m,qq,k;
    
    int dis[MAXN][2050];
    bool vis[MAXN][2050];
    
    int main() {
        freopen("move.in","r",stdin);
        freopen("move.out","w",stdout);
        n = read();
        m = read();
        qq = read();
        k = read();
        if(k > qq)k = qq;
        for(int i = 1; i <= m; i++) {
            int vi = read(),vj = read(),wei = read();
            push1(vi,vj,wei);
        }
        for(int i = 1; i <= qq; i++) {
            int vi = read(),vj = read(),wei = read();
            push2(vi,vj,wei);
        }
    
        memset(dis,0x3e,sizeof(dis));
        dis[1][0] = 0;
        be.now = 1;
        be.used = 0;
        q.push(be);
        while(!q.empty()) {
            Note op = q.front();
            q.pop();
            vis[op.now][op.used] = false;
            int now = op.now;
            int us = op.used;
            for(int i = head1[now]; i; i = edge1[i].nxt) {
                int vj = edge1[i].vj;
                if(dis[now][us] + edge1[i].wei < dis[vj][us]) {
                    dis[vj][us] = dis[now][us] + edge1[i].wei;
                    Note zz;
                    zz.used = op.used;
                    zz.now = vj;
                    if(vis[zz.now][zz.used])continue;
                    vis[zz.now][zz.used] = true;
                    q.push(zz);
                }
            }
            if(op.used >= k)continue;
            for(int i = head2[now]; i; i = edge2[i].nxt) {
                int vj = edge2[i].vj;
                if(dis[now][us] + edge2[i].wei < dis[vj][us + 1]) {
                    dis[vj][us + 1] = dis[now][us] + edge2[i].wei;
                    Note zz;
                    zz.used = op.used + 1;
                    zz.now = vj;
                    if(vis[zz.now][zz.used])continue;
                    vis[zz.now][zz.used] = true;
                    q.push(zz);
                }
            }
    
        }
        int ans = 0x3e3e3e3e;
        for(int i = 0; i <= min(k,qq); i++) {
            ans = min(ans,dis[n][i]);
        }
        printf("%d",ans == 0x3e3e3e3e ? -1:ans);
        return 0;
    }
  • 相关阅读:
    成功,离你只有一步之遥
    多灾多难!危机下给企业家们的十大贴心忠告
    《赢道:成功创业者的28条戒律》 简介:
    面对大面积失业潮,普通人有无必要创业?
    赢在行动《越狱》给创业者的启示
    如何优选创业项目、产品和服务
    你是高执行力人才吗?
    创业新闻] 2009年创业者必读的十一本书(转)
    赢在2009 创业者需练好六脉神剑(转)
    相当受用!10个从实质上迅速提升经理人生活的方法
  • 原文地址:https://www.cnblogs.com/luoyibujue/p/7716620.html
Copyright © 2020-2023  润新知