acwing刷题

13 篇文章 0 订阅

目录

1 1117 单词接龙

 2 1118 分成互质组

3 1068 环形石子合并

4 1129 热浪

 5 1128 信使

6 1126 最小花费

7 1135 新年好

8 1134 最短路计数

9 1137 选择最佳路线

10 1131 拯救大兵瑞恩


1 1117 单词接龙

单词接龙是一个与我们经常玩的成语接龙相类似的游戏。

现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”,每个单词最多被使用两次。

在两个单词相连时,其重合部分合为一部分,例如 beast 和 astonish ,如果接成一条龙则变为 beastonish。

我们可以任意选择重合部分的长度,但其长度必须大于等于1,且严格小于两个串的长度,例如 at 和 atide 间不能相连。

输入格式

输入的第一行为一个单独的整数 n 表示单词数,以下 n 行每行有一个单词(只含有大写或小写字母,长度不超过20),输入的最后一行为一个单个字符,表示“龙”开头的字母。

你可以假定以此字母开头的“龙”一定存在。

输出格式

只需输出以此字母开头的最长的“龙”的长度。

数据范围

n≤20,
单词随机生成。

输入样例:

5
at
touch
cheat
choose
tact
a

输出样例:

23

提示

连成的“龙”为 atoucheatactactouchoose。

#include<bits/stdc++.h>
using namespace std;
string a[25];
int used[25];
int g[25][25];
int ans=0;
int n;
void dfs(string b,int u)
{
    ans=max((int)b.size(),ans);
    used[u]++;
    for(int i=0;i<n;i++){
        if(g[u][i]&&used[i]<2){
            dfs(b+a[i].substr(g[u][i]),i);
        }
    }

    used[u]--;
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)cin>>a[i];
    char ch;
    cin>>ch;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            string s=a[i],h=a[j];
            for(int k=1;k<min(s.size(),h.size());k++){
                if(s.substr(s.size()-k,k)==h.substr(0,k)){
                    g[i][j]=k;
                    break;
                }
            }
        }
    }
    for(int i=0;i<n;i++){
        if(a[i][0]==ch){
            dfs(a[i],i);
        }
    }
    cout<<ans;
    return 0;
}

 2 1118 分成互质组

给定 n个正整数,将它们分组,使得每组中任意两个数互质。

至少要分成多少个组?

输入格式

第一行是一个正整数 n。

第二行是 n 个不大于10000的正整数。

输出格式

一个正整数,即最少需要的组数。

数据范围

1≤n≤10

输入样例:

6
14 20 33 117 143 175

输出样例:

3

#include<bits/stdc++.h>
using namespace std;
int n;
int a[15];
int gr[15][15],ans=10;
bool st[15];
int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}
bool check(int gr[],int gc,int i)
{
    for(int j=0;j<gc;j++){
        if(gcd(a[gr[j]],a[i])>1)return false;
    }
    return true;
}
void dfs(int g,int gc,int tc,int start)
{
    if(g>=ans)return ;
    if(tc==n)ans=g;
    bool flag=true;
    for(int i=start;i<n;i++){
        if(!st[i]&&check(gr[g],gc,i)){
            st[i]=true;
            gr[g][gc]=i;
            dfs(g,gc+1,tc+1,i+1);
            st[i]=false;
            flag=false;
        }
    }
    if(flag)dfs(g+1,0,tc,0);

}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)cin>>a[i];
    dfs(1,0,0,0);
    cout<<ans;
    return 0;
}

3 1068 环形石子合并

将n堆石子绕圆形操场排放,现要将石子有序地合并成一堆。规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆的石子数记做该次合并的得分。
请编写一个程序,读入堆数n及每堆的石子数,并进行如下计算:

  • 选择一种合并石子的方案,使得做n−1次合并得分总和最大。
  • 选择一种合并石子的方案,使得做n−1次合并得分总和最小。

输入

输入第一行一个整数n(1≤n≤200),表示有n堆石子。
第二行n个整数,表示每堆石子的数量。

输出

输出共两行:
第一行为合并得分总和最小值,
第二行为合并得分总和最大值。

样例输入 Copy

4
4 5 9 4

样例输出 Copy

43
54
#include<bits/stdc++.h>
using namespace std;
int a[405];
int f[405][405],g[405][405];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        a[i+n]=a[i];
    }
    for(int i=1;i<=n*2;i++){
        a[i]+=a[i-1];
    }
    memset(f,0x3f,sizeof f);
    memset(g,-0x3f,sizeof g);
    for(int len=1;len<=n;len++){
        for(int l=1;l+len-1<=n*2;l++){
            int r=l+len-1;
            if(len==1)f[l][r]=g[l][r]=0;
            else{
                for(int k=l;k<r;k++){
                    f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]+a[r]-a[l-1]);
                    g[l][r]=max(g[l][r],g[l][k]+g[k+1][r]+a[r]-a[l-1]);
                }
            }
        }
    }
    int ans1=-1e9,ans2=1e9;
    for(int i=1;i<=n;i++){
        ans1=max(ans1,g[i][i+n-1]);
        ans2=min(ans2,f[i][i+n-1]);
    }
    cout<<ans2<<endl<<ans1;
    return 0;
}

 从今天开始开始让我最头疼的两个部分了

先从图论开始,后面开始数论

4 1129 热浪

德克萨斯纯朴的民众们这个夏天正在遭受巨大的热浪!!!

他们的德克萨斯长角牛吃起来不错,可是它们并不是很擅长生产富含奶油的乳制品。

农夫John此时身先士卒地承担起向德克萨斯运送大量的营养冰凉的牛奶的重任,以减轻德克萨斯人忍受酷暑的痛苦。

John已经研究过可以把牛奶从威斯康星运送到德克萨斯州的路线。

这些路线包括起始点和终点一共有 T 个城镇,为了方便标号为 11 到 T。

除了起点和终点外的每个城镇都由 双向道路 连向至少两个其它的城镇。

每条道路有一个通过费用(包括油费,过路费等等)。

给定一个地图,包含 C条直接连接 2 个城镇的道路。

每条道路由道路的起点 Rs,终点 Re 和花费 Ci 组成。

求从起始的城镇 Ts 到终点的城镇 Te 最小的总费用。

输入格式

第一行: 4 个由空格隔开的整数: T,C,Ts,Te;

第 2 到第 C+1 行: 第 i+1 行描述第 i 条道路,包含 33 个由空格隔开的整数: Rs,Re,Ci。

输出格式

一个单独的整数表示从 Ts 到 Te 的最小总费用。

数据保证至少存在一条道路。

数据范围

1≤T≤2500,
1≤C≤6200,
1≤Ts,Te,Rs,Re≤T,
1≤Ci≤1000

输入样例:

7 11 5 4
2 4 2
1 4 3
7 2 2
3 4 3
5 7 5
7 3 3
6 1 1
6 3 4
2 4 3
5 6 3
7 2 1

输出样例:

7

#include<bits/stdc++.h>
using namespace std;
const int N=6200*2+10;
int e[N],ne[N],h[N],w[N],idx;
int n,m,s,t;
bool st[N];
int d[N];
void add(int a,int b,int c)
{
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
void spfa()
{
    memset(d,0x3f,sizeof d);
    d[s]=0;
    queue<int>q;
    q.push(s);
    st[s]=true;
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=false;
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(d[j]>d[t]+w[i]){
                d[j]=d[t]+w[i];
                if(!st[j]){
                    q.push(j);
                    st[j]=true;
                }
            }

        }
    }

}
int main()
{
    cin>>n>>m>>s>>t;
    memset(h,-1,sizeof h);
    for(int i=0;i<m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c),add(b,a,c);
    }
    spfa();
    cout<<d[t];

    return 0;
}

 5 1128 信使

战争时期,前线有 n 个哨所,每个哨所可能会与其他若干个哨所之间有通信联系。

信使负责在哨所之间传递信息,当然,这是要花费一定时间的(以天为单位)。

指挥部设在第一个哨所。

当指挥部下达一个命令后,指挥部就派出若干个信使向与指挥部相连的哨所送信。

当一个哨所接到信后,这个哨所内的信使们也以同样的方式向其他哨所送信。信在一个哨所内停留的时间可以忽略不计

直至所有 n个哨所全部接到命令后,送信才算成功。

因为准备充足,每个哨所内都安排了足够的信使(如果一个哨所与其他 k 个哨所有通信联系的话,这个哨所内至少会配备 k 个信使)。

现在总指挥请你编一个程序,计算出完成整个送信过程最短需要多少时间。

输入格式

第 11 行有两个整数 n 和 m,中间用 11 个空格隔开,分别表示有 n 个哨所和 m 条通信线路。

第 22 至 m+1 行:每行三个整数 i、j、k,中间用 11 个空格隔开,表示第 i 个和第 j 个哨所之间存在 双向 通信线路,且这条线路要花费 k 天。

输出格式

一个整数,表示完成整个送信过程的最短时间。

如果不是所有的哨所都能收到信,就输出-1。

数据范围

1≤n≤100,
1≤m≤200,
1≤k≤1000

输入样例:

4 4
1 2 4
2 3 7
2 4 1
3 4 6

输出样例:

11

#include<bits/stdc++.h>
using namespace std;
const int N=2010;
int e[N],ne[N],h[N],w[N],idx;
int n,m,d[N];
bool st[N];
void add(int a,int b,int c)
{
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
void spfa()
{
    queue<int>q;
    q.push(1);
    st[1]=true;
    memset(d,0x3f,sizeof d);
    d[1]=0;
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=false;
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(d[j]>d[t]+w[i]){
                d[j]=d[t]+w[i];
                if(!st[j]){
                    q.push(j);
                    st[j]=true;
                }
            }
        }
    }
}
int main()
{
    cin>>n>>m;
    memset(h,-1,sizeof h);
    for(int i=0;i<m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c),add(b,a,c);
    }
    spfa();
    int ans=0;
    for(int i=1;i<=n;i++)ans=max(ans,d[i]);
    if(ans==0x3f3f3f3f)cout<<-1;
    else cout<<ans;
    return 0;
}

6 1126 最小花费

在 n 个人中,某些人的银行账号之间可以互相转账。

这些人之间转账的手续费各不相同。

给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问 A� 最少需要多少钱使得转账后 B收到 100 元。

输入格式

第一行输入两个正整数 n,m,分别表示总人数和可以互相转账的人的对数。

以下 m 行每行输入三个正整数 x,y,z,表示标号为 x 的人和标号为 y 的人之间互相转账需要扣除 z% 的手续费 ( z<100 )。

最后一行输入两个正整数 A,B。

数据保证 A 与 B 之间可以直接或间接地转账。

输出格式

输出 A 使得 B 到账 100 元最少需要的总费用。

精确到小数点后 8 位。

数据范围

1≤n≤2000
m≤105

输入样例:

3 3
1 2 1
2 3 2
1 3 3
1 3

输出样例:

103.07153164
#include<bits/stdc++.h>
using namespace std;
const int N=2010;
double g[N][N];
double d[N];
int n,m,S,T;
bool st[N];
void djk()
{
    d[S]=1;
    for(int i=1;i<=n;i++){
        int t=-1;
        for(int j=1;j<=n;j++)
        {
            if(!st[j]&&(t==-1||d[t]<d[j]))t=j;
        }
        st[t]=true;
        for(int j=1;j<=n;j++){
            d[j]=max(d[j],d[t]*g[t][j]);
        }
    }

}
int main()
{
    cin>>n>>m;
    while(m--){
        int a,b,c;
        cin>>a>>b>>c;
        double z=(100.0-c)/100;
        g[a][b]=g[b][a]=max(g[a][b],z);
    }
    cin>>S>>T;
    djk();
    printf("%.8lf",100/d[T]);
    return 0;
}

7 1135 新年好

重庆城里有 n个车站,m 条 双向 公路连接其中的某些车站。

每两个车站最多用一条公路连接,从任何一个车站出发都可以经过一条或者多条公路到达其他车站,但不同的路径需要花费的时间可能不同。

在一条路径上花费的时间等于路径上所有公路需要的时间之和。

佳佳的家在车站 11,他有五个亲戚,分别住在车站 a,b,c,d,e。

过年了,他需要从自己的家出发,拜访每个亲戚(顺序任意),给他们送去节日的祝福。

怎样走,才需要最少的时间?

输入格式

第一行:包含两个整数 n,m,分别表示车站数目和公路数目。

第二行:包含五个整数 a,b,c,d,e,分别表示五个亲戚所在车站编号。

以下 m 行,每行三个整数 x,y,t,表示公路连接的两个车站编号和时间。

输出格式

输出仅一行,包含一个整数 T,表示最少的总时间。

数据范围

1≤n≤50000
1≤m≤105,
1<a,b,c,d,e≤n
1≤x,y≤n
1≤t≤100

输入样例:

6 6
2 3 4 5 6
1 2 8
2 3 3
3 4 4
4 5 5
5 6 2
1 6 7

输出样例:

21

#include<bits/stdc++.h>
using namespace std;
const int N=50010,M=200010;
int d[6][N];
bool st[N];
int s[6];
int e[M],ne[M],h[M],w[M],idx;
void add(int a,int b,int c)
{
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
void spfa(int start,int d[])
{
    queue<int>q;
    memset(d,0x3f,4*N);
    d[start]=0;
    q.push(start);
    st[start]=true;
    while(q.size()){
        int t=q.front();
        q.pop();
        st[t]=false;
        for(int i=h[t];i!=-1;i=ne[i]){
            int j=e[i];
            if(d[j]>d[t]+w[i]){
                d[j]=d[t]+w[i];
                if(!st[j]){
                    q.push(j);
                    st[j]=true;
                }
            }
        }
    }
}
int dfs(int u,int start,int dist)
{
    if(u==6)return dist;
    int res=0x3f3f3f3f;
    for(int i=1;i<=5;i++){
        if(!st[i]){
            int ne=s[i];
            st[i]=true;
            res=min(res,dfs(u+1,i,dist+d[start][ne]));
            st[i]=false;
        }
    }
    return res;
}
int main()
{
    int n,m;
    cin>>n>>m;
    s[0]=1;
    memset(h,-1,sizeof h);
    for(int i=1;i<=5;i++)cin>>s[i];
    while(m--){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c),add(b,a,c);
    }
    for(int i=0;i<6;i++)spfa(s[i],d[i]);
    cout<<dfs(1,0,0);
    return 0;
}

8 1134 最短路计数

给出一个 N 个顶点 M 条边的无向无权图,顶点编号为 1 到 N。

问从顶点 1 开始,到其他每个点的最短路有几条。

输入格式

第一行包含 2 个正整数 N,M,为图的顶点数与边数。

接下来 M 行,每行两个正整数一 x,y表示有条顶点 x 连向顶点 y 的边,请注意可能有自环与重边。

输出格式

输出 N 行,每行一个非负整数,第 i 行输出从顶点 1 到顶点 i 有多少条不同的最短路,由于答案有可能会很大,你只需要输出对 100003 取模后的结果即可。

如果无法到达顶点 i 则输出 0。

数据范围

1≤N≤105
1≤M≤2×105

输入样例:

5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5

输出样例:

1
1
1
2
4

#include<bits/stdc++.h>
using namespace std;
const int N=400010;
int e[N],ne[N],h[N];
int d[N],cnt[N];
int n,m,idx;
void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void bfs()
{
    queue<int>q;
    q.push(1);
    memset(d,0x3f,sizeof d);
    d[1]=0;
    cnt[1]=1;
    while(q.size())
    {
        int t=q.front();
        q.pop();
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(d[j]>d[t]+1){
                d[j]=d[t]+1;
                cnt[j]=cnt[t];
                q.push(j);
            }else if(d[j]==d[t]+1){
                d[j]=d[t]+1;
                cnt[j]=(cnt[j]+cnt[t])%100003;
            }
        }
    }

}
int main()
{
    scanf("%d%d",&n,&m);
    memset(h,-1,sizeof h);
    while(m--){
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b),add(b,a);
    }
    bfs();
    for(int i=1;i<=n;i++)printf("%d\n",cnt[i]);
    return 0;
}

9 1137 选择最佳路线

有一天,琪琪想乘坐公交车去拜访她的一位朋友。

由于琪琪非常容易晕车,所以她想尽快到达朋友家。

现在给定你一张城市交通路线图,上面包含城市的公交站台以及公交线路的具体分布。

已知城市中共包含 n 个车站(编号1~n)以及 m 条公交线路。

每条公交线路都是 单向的,从一个车站出发直接到达另一个车站,两个车站之间可能存在多条公交线路。

琪琪的朋友住在 s 号车站附近。

琪琪可以在任何车站选择换乘其它公共汽车。

请找出琪琪到达她的朋友家(附近的公交车站)需要花费的最少时间。

输入格式

输入包含多组测试数据。

每组测试数据第一行包含三个整数 n,m,s,分别表示车站数量,公交线路数量以及朋友家附近车站的编号。

接下来 m 行,每行包含三个整数 p,q,t,表示存在一条线路从车站 p 到达车站 q,用时为 t。

接下来一行,包含一个整数 w,表示琪琪家附近共有 w 个车站,她可以在这 w 个车站中选择一个车站作为始发站。

再一行,包含 w 个整数,表示琪琪家附近的 w 个车站的编号。

输出格式

每个测试数据输出一个整数作为结果,表示所需花费的最少时间。

如果无法达到朋友家的车站,则输出 -1。

每个结果占一行。

数据范围

n≤1000,m≤20000
1≤s≤n
0<w<n
0<t≤1000

输入样例:

5 8 5
1 2 2
1 5 3
1 3 4
2 4 7
2 5 6
2 3 5
3 5 1
4 5 1
2
2 3
4 3 4
1 2 3
1 3 4
2 3 2
1
1

输出样例:

1
-1

#include<bits/stdc++.h>
using namespace std;
const int N=25010;
int e[N],ne[N],w[N],h[N],idx;
int d[N];
bool st[N];
int n,m,T;
void add(int a,int b,int c)
{
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
int spfa()
{
    queue<int>q;
    q.push(0);
    memset(d,0x3f,sizeof d);
    d[0]=0;
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=false;
        for(int i=h[t];i!=-1;i=ne[i]){
            int j=e[i];
            if(d[j]>d[t]+w[i]){
                d[j]=d[t]+w[i];
                if(!st[j]){
                    q.push(j);
                    st[j]=true;
                }
            }
        }
    }
    if(d[T]==0x3f3f3f3f)return -1;
    return d[T];
}
int main()
{
    while(scanf("%d%d%d",&n,&m,&T)!=EOF){
        memset(h,-1,sizeof h);
        idx=0;
        while(m--){
            int a,b,c;
            cin>>a>>b>>c;
            add(a,b,c);
        }
        int s;
        scanf("%d",&s);
        while(s--){
            int v;
            cin>>v;
            add(0,v,0);
        }
        printf("%d\n",spfa());
    }
    return 0;
}

10 1131 拯救大兵瑞恩

1944 年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩。

瑞恩被关押在一个迷宫里,迷宫地形复杂,但幸好麦克得到了迷宫的地形图。

迷宫的外形是一个长方形,其南北方向被划分为 N 行,东西方向被划分为 M 列, 于是整个迷宫被划分为 N×M 个单元。

每一个单元的位置可用一个有序数对 (单元的行号, 单元的列号) 来表示。

南北或东西方向相邻的 22 个单元之间可能互通,也可能有一扇锁着的门,或者是一堵不可逾越的墙。

注意: 门可以从两个方向穿过,即可以看成一条无向边。

迷宫中有一些单元存放着钥匙,同一个单元可能存放 多把钥匙,并且所有的门被分成 P 类,打开同一类的门的钥匙相同,不同类门的钥匙不同。

大兵瑞恩被关押在迷宫的东南角,即 (N,M)单元里,并已经昏迷。

迷宫只有一个入口,在西北角。

也就是说,麦克可以直接进入 (1,1) 单元。

另外,麦克从一个单元移动到另一个相邻单元的时间为 11,拿取所在单元的钥匙的时间以及用钥匙开门的时间可忽略不计。

试设计一个算法,帮助麦克以最快的方式到达瑞恩所在单元,营救大兵瑞恩。

输入格式

第一行有三个整数,分别表示 N,M,P 的值。

第二行是一个整数 k,表示迷宫中门和墙的总数。

接下来 k 行,每行包含五个整数,Xi1,Yi1,Xi2,Yi2,Gi当 Gi≥1 时,表示 (Xi1,Yi1) 单元与 (Xi2,Yi2)单元之间有一扇第 Gi 类的门,当 Gi=0 时,表示 (Xi1,Yi1) 单元与 (Xi2,Yi2) 单元之间有一面不可逾越的墙。

接下来一行,包含一个整数 S,表示迷宫中存放的钥匙的总数。

接下来 S 行,每行包含三个整数 Xi1,Yi1,Qi,表示 (Xi1,Yi1) 单元里存在一个能开启第 Qi 类门的钥匙。

输出格式

输出麦克营救到大兵瑞恩的最短时间。

如果问题无解,则输出 -1。

数据范围

|Xi1−Xi2|+|Yi1−Yi2|=1
0≤Gi≤P
1≤Qi≤P
1≤N,M,P≤10
1≤k≤150

输入样例:

4 4 9
9
1 2 1 3 2
1 2 2 2 0
2 1 2 2 0
2 1 3 1 0 
2 3 3 3 0
2 4 3 4 1
3 2 3 3 0
3 3 4 3 0
4 3 4 4 0
2
2 1 2 
4 2 1

输出样例:

14

样例解释:

迷宫如下所示:

#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
const int N=11,M=N*N,E=400,P=1<<10;
int h[M],e[E],ne[E],w[E],idx;
int d[M][P];
int g[N][N],key[M];
bool st[M][P];
typedef pair<int,int>PII;
set<PII>edge;
int n,m,p,k;
void add(int a,int b,int c)
{
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
void build()
{
    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            for(int u=0;u<4;u++){
                int x=i+dx[u],y=j+dy[u];
                if(!x||x>n||!y||y>m)continue;
                int a=g[i][j],b=g[x][y];
                if(edge.count({a,b})==0)add(a,b,0);
            }
        }
    }

}
int bfs()
{
    deque<PII>q;
    q.push_back({1,0});
    memset(d,0x3f,sizeof d);
    d[1][0]=0;
    while(q.size())
    {
        auto t=q.front();
        q.pop_front();
        if(st[t.x][t.y])continue;
        st[t.x][t.y]=true;
        if(t.x==n*m)return d[t.x][t.y];
        if(key[t.x]){
            int state=t.y|key[t.x];
            if(d[t.x][state]>d[t.x][t.y]){
                d[t.x][state]=d[t.x][t.y];
                q.push_front({t.x,state});
            }
        }
        for(int i=h[t.x];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(w[i]&&!(t.y>>w[i]-1&1))continue;
            if(d[j][t.y]>d[t.x][t.y]+1){
                d[j][t.y]=d[t.x][t.y]+1;
                q.push_back({j,t.y});
            }
        }
    }
}
int main()
{
    cin>>n>>m>>p>>k;
    memset(h,-1,sizeof h);
    for(int i=1,t=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            g[i][j]=t++;
        }
    }
    while(k--){
        int x1,y1,x2,y2,c;
        cin>>x1>>y1>>x2>>y2>>c;
        int a=g[x1][y1],b=g[x2][y2];
        edge.insert({a,b});
        edge.insert({b,a});
        if(c)add(a,b,c),add(b,a,c);
    }
    build();
    int s;
    cin>>s;
    while(s--){
        int x,y,id;
        cin>>x>>y>>id;
        key[g[x][y]]|=1<<id-1;
    }
    cout<<bfs();
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值