华东交通大学2022双基ACM竞赛

比赛链接:https://ac.nowcoder.com/acm/contest/44482

签到:AEI

碎碎念:好家伙,题目里全是心怡。

A:心怡的魔法城堡

原题链接心怡的魔法城堡
题意:闯入者可以选择到达上出口或者下出口,求最短时间。很明显对于每个勇者分别求到达上下出口所需时间取较小值相加即可。
代码

int main()
{
    LL ans = 0;
    cin >> n >> m >> t;
    for(int i = 1; i <= n; i ++ ){
        int x;
        cin >> x;
        ans += min(x - 1, m - x) * t;
    }
    cout << ans << endl;
    return 0;
}

E:心怡的羊驼

原题链接心怡的羊驼
题意:求出给出的两位数中个位和十位相加的最大值
代码

int main()
{
    int num ,ans = -INF;
    cin >> n;
    for(int i = 1; i <= n; i ++){
        int x;
        cin >> x;
        int tmp;
        tmp = x % 10 + x / 10;
        if(tmp > ans){
            ans = tmp;
            num = x;
        }
    }    
    cout << num << endl;
    return 0;
}

I:一只迷失的羊驼

原题链接一只迷失的羊驼
题意:bfs最短路模板题。
代码

const int N = 110;
int n,m;
int a,b,x,y;
int g[N][N];
int d[N][N];
int dx[]={1,0,-1,0};
int dy[]= {0,1,0,-1};

void bfs()
{
    memset(d,-1,sizeof d);
    queue<PII> q;
    q.push({a,b});
    d[a][b] = 0;
    
    while(q.size()){
        auto t = q.front();
        q.pop();
        
        for(int i = 0; i < 4; i ++ ){
            int xx = t.first + dx[i], yy = t.second + dy[i];
            if( xx <= 0 || xx > n || yy <= 0 || yy > m || g[xx][yy] == 1)   continue;
            if(d[xx][yy] != -1)     continue;
            d[xx][yy] = d[t.first][t.second] + 1;
            q.push({xx,yy});
        }
    }
}
int main()
{
    cin >> n >> m;
    cin >> a >> b >> x >> y;
    for(int i = 1; i <= n; i ++ ){
        for(int j = 1; j <= m; j ++ ){
            cin >> g[i][j];
        }
    }
    
    bfs();
    
    cout << d[x][y] << endl;
    return 0;
}


中等:BCD

B:火车摆放

原题链接火车摆放
题意:首先,我们需要思考如何考虑火车摆放情况,可以开一个数组a,a[x]=1表示被摆放好,反之则a[x]=0,在这里我们选择使用sets来表示火车的摆放情况,如果火车拜访好了,则在s中删除该火车,反正则插入s中。需要注意的是在s初始化的过程中我们需要把n+1也插入当中。
如果以x为火车头的火车长度为len,则表示x带x+len-1这一段的和为len,即区间长度。一旦超过了这个长度,那么区间和总是小于这个区间长度。所以我们可以二分区间长度。在本题中我们选择使用set可以方便解决此问题。如果查询的x存在与s中,则表示x暂未排好直接输出0即可,否则查找s中第一个大于x的数减去x即为答案。
代码

const int N = 2e5 + 10;
int n,m;
int opt,x;
int h[N];
set<int> s;

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i ++ )
        s.insert(i);
    s.insert(n+1);
    while( m -- ){
        cin >> opt >> x;
        if(opt == 1){
            if(s.count(x)){
                s.erase(x);
            }
        }else if(opt == 2){
            s.insert(x);
        }else{
            if(s.count(x)) cout << 0 << endl;
            else{
                cout << *s.upper_bound(x) -  x<< endl;
            }
        }
    }
    return 0;
}

C:n层妖塔

原题链接n层妖塔
题意:假设我们从第i层通关需要的战力为x。如果战力s>x,那么可以一路平推。如果s<=x,那么我们不妨先将战力修炼到x在一路通关。
为此我们可以现预处理出从第i层开始挑战至少需要多少战力才能一路平推。可以得出公式\(f_i=max(a[i]+1,f_{i+1}-1)\)。时间复杂度为\(O(n+m)\)
代码

const int N = 100005;
int n,m;
int s,b;
int a[N];

int main()
{
    memset(a, -0x3f, sizeof a);
    cin >> n >> m;
    for(int i = 1; i <= n; i ++ )    cin >> a[i];
    for(int i = n ; i >= 1; i-- )    a[i] = max(a[i] + 1,a[i+1] - 1);
    
    while(m -- ){
        cin >> s >> b;
        if(s > a[b])    cout << n - b + 1 << endl;
        else cout << n - b + 1 + a[b] - s  << endl;
    }
    return 0;
}

D:铁路

原题链接铁路
题意:因为本题中图为稀疏图。且q<=1000,所以采用暴力迪杰斯特拉O(mq)也是可以过的。当然本题目有更好的解法,因为需要多次询问且n较小,所以可以采用Floyd算法较快通过此题,opt=2时更新g即可,\(g[i][j]=min(g[i][j],g[i][a]+g[a][b]+a[b][j],g[i][b]+g[b][a]+g[a][j])\)。复杂度为O(\(n^3*q\))。
代码

//迪杰斯特拉算法

const int N = 210;
int g[N][N];
int n,m,q;
int dist[N];
bool st[N];

int dijkstra(int x,int y)
{
    memset(dist,0x3f,sizeof dist);
    memset(st,0,sizeof st);
    dist[x] = 0;

    for(int i = 0; i < n - 1; i ++ ){
        int t = -1;
        for(int j = 1; j <= n; j ++ ){
            if(!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        }

        for(int j = 1; j <= n; j ++ )
            dist[j] = min(dist[j] , dist[t] + g[t][j]);

        st[t] = true;
    }

    return dist[y];
}
int main()
{
    memset(g,0x3f,sizeof g);
    cin >> n >> m >> q;
    while(m -- ){
        int a,b,c;
        cin >> a >> b >> c;
        g[a][b] = min(g[a][b],c);
        g[b][a] = min(g[b][a],c);
    }
    while(q -- ){
        int opt;
        cin >> opt;
        int a,b,c;
        if(opt == 1){
            cin >> a >> b;
            cout << dijkstra(a,b) << endl;
        }
        else {
            cin >> a >> b >> c;
            g[a][b] = g[b][a] = min(g[a][b],c);
        }
    }
    return 0;
}
//Floyd算法

const int N = 210;
int g[N][N];
int n,m,q;

void Init()
{
    for(int k = 1; k <= n; k ++ ){
        for(int i = 1; i <= n; i ++ ){
            for(int j = 1; j <= n; j ++){
                g[i][j] = min(g[i][j],g[i][k]+g[k][j]);
            }
        }
    }
}

void update(int k)
{
     for(int i = 1; i <= n; i ++ ){
            for(int j = 1; j <= n; j ++){
                g[i][j] = min(g[i][j],g[i][k]+g[k][j]);
            }
        }
}

int main()
{
    memset(g,0x3f,sizeof g);
    cin >> n >> m >> q;
    while(m -- ){
        int a,b,c;
        cin >> a >> b >> c;
        g[a][b] = min(g[a][b],c);
        g[b][a] = min(g[b][a],c);
    }
    Init();
    while(q -- ){
        int opt;
        cin >> opt;
        int a,b,c;
        if(opt == 1){
            cin >> a >> b;
            if(a == b)    cout << 0 << endl;
            else cout << g[a][b] << endl;
        }
        else {
            cin >> a >> b >> c;
            g[a][b] = g[b][a] = min(g[a][b],c);
            update(a);
            update(b);
        }
    }
    return 0;
}

困难:FGH

F:小纸条

原题链接小纸条

G: 地牢探险

原题链接地牢探险

H:序列

原题链接序列

posted @ 2022-11-19 21:20  车车学不完  阅读(151)  评论(0)    收藏  举报