代码源周赛[R47C]数字与字母

题目传送门

这个题目是一道图论题,其实一开始我没有想出来,我直接大模拟+小贪心。发现第二个样例没有过。那么这个题目是怎么跟图论扯上关系。
题目中说了,数字可以轮换,字母也可以轮换。那么我们就可以建图了,相邻的数字之间建一条边,边权为1。相邻的字母也建一条边,边权也是1。
题目中还说了,'0'到9'分别对应'a'到'z'。建10条边,每一条边权是0,这个很关键,题目中说了。

所以,建图的代码如下

for(int i=0;i<=9;i++){
        edge[i].push_back({(i-1+10)%10,1});
        edge[i].push_back({(i+1+10)%10,1});
    }
    for(int i=0;i<=25;i++){
        edge[i+10].push_back({(i-1+26)%26+10,1});
        edge[i+10].push_back({(i+1+26)%26+10,1});
    }
    for(int i=0;i<=9;i++){
        edge[i].push_back({i+10,0});
        edge[i+10].push_back({i,0});
    }

从上面代码不难看出,'0'到'9'分别对应的就是0到9编码,'a'到'z'对应的是10到35

然后,我们对于字符串每一位,都跑一边最短路就可以了。不管你用SPFA,Bellman-ford,Dijsktra,Floyd,甚至是0-1BFS,都行
我写的是Dijstrak

代码如下

#include<bits/stdc++.h>
using namespace std;

struct node{
    int y,v;
};

vector<node> edge[100];
char s[200005],t[200005];
int n,dist[100];
set<pair<int,int>> q;

int dij(int s,int t){
    memset(dist,127,sizeof dist);
    dist[s]=0;q.clear();
    for(int i=0;i<=40;i++)
        q.insert({dist[i],i});
    while(q.size()){
        int x=q.begin()->second;
        q.erase(q.begin());
        if(x==t||dist[x]>1<<30) break;
        for(auto [y,v]:edge[x]){
            if(dist[x]+v<dist[y]){
                q.erase({dist[y],y});
                dist[y]=dist[x]+v;
                q.insert({dist[y],y});
            }
        }
    }
    return dist[t];
}

int main(){
    cin.tie(0)->sync_with_stdio(0);
    cin>>n>>s+1>>t+1;
    for(int i=0;i<=9;i++){
        edge[i].push_back({(i-1+10)%10,1});
        edge[i].push_back({(i+1+10)%10,1});
    }
    for(int i=0;i<=25;i++){
        edge[i+10].push_back({(i-1+26)%26+10,1});
        edge[i+10].push_back({(i+1+26)%26+10,1});
    }
    for(int i=0;i<=9;i++){
        edge[i].push_back({i+10,0});
        edge[i+10].push_back({i,0});
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        int s_px,t_px;
        if('0'<=s[i]&&s[i]<='9') s_px=s[i]-'0';
        else s_px=s[i]-'a'+10;
        if('0'<=t[i]&&t[i]<='9') t_px=t[i]-'0';
        else t_px=t[i]-'a'+10;
        ans+=dij(s_px,t_px);
    }
    cout<<ans<<endl;
}

我一开始忘了dij板子怎么写了,然后抄了一下老师的,但是原封不动的抄了。把初始化q的0到40原封不动的抄成了1到n。害得我没调出来,赛时没有过。
以后这种板子一定要背熟,哪有考试的时候找板子的啊!

posted @ 2026-01-23 23:04  zhangruotian_Max  阅读(0)  评论(0)    收藏  举报