• 菲律宾海战


    这个题没有什么可写的部分分吧

    比较套路的一个题

    两种其实差不多的解法

    1,DP最短路

    回顾最短路的实现中,我们用len[i]表示从起点到i这个点的最短距离

    那么加入减小边权了呢,我们可以用len[i][j]表示到第i个点,用掉k次减少边权机会的最小距离

    转移是显然的,在普通最短路转移的基础上,加入从用掉j个支援到用j+1个的转移,

    len[v][j+1]=min(len[v][j+1],len[u][j]+dis[u][v]/2)

    最后取min(len[n][i])(i属于{[1,k]})即可

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    using namespace std;
    const int maxn=60;
    int n,m,ki,len[maxn][maxn],e[maxn][maxn];
    bool exist[maxn][maxn];
    int spfa()
    {
        queue<int>q,qs;
        memset(len,0x3f,sizeof(len));
        len[1][0]=0;
        exist[1][0]=1;
        q.push(1),qs.push(0);
        while(!q.empty())
        {
            int i=q.front(),k=qs.front();
            q.pop(),qs.pop();
            exist[i][k]=0;
            for(int j=1;j<=n;j++)
            {
                if(e[i][j]>1e6)
                    continue;
                if(len[j][k]>len[i][k]+e[i][j])
                {
                    len[j][k]=len[i][k]+e[i][j];
                    if(!exist[j][k])
                        exist[j][k]=1,q.push(j),qs.push(k);
                }
                if(len[j][k+1]>len[i][k]+e[i][j]/2)
                {
                    len[j][k+1]=len[i][k]+e[i][j]/2;
                    if(!exist[j][k+1]&&k<ki)
                        exist[j][k+1]=1,q.push(j),qs.push(k+1);
                }
            }
        }
        int ret=1e9;
        for(int i=0;i<=ki;i++)
            ret=min(ret,len[n][i]);
        return ret;
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&ki);
        memset(e,0x3f,sizeof(e));
        for(int x,y,d,i=1;i<=m;i++)
        {
            scanf("%d%d%d",&x,&y,&d);
            e[x][y]=e[y][x]=d;
        }
        printf("%d
    ",spfa());
        return 0;
    }


    2,分层图最短路

    本来是有n个点的,但是不好处理,我们不妨把每个点拆成k+1个,第j个表示到这个点要用j次支援

    建图的时候同层正常连边,本层到上层连边时边权除2,直接跑最短路,统计答案时枚举第n个点各层最小代价即可

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    using namespace std;
    const int maxn=2600;
    struct edge{
        int next,to,dis;
    }e[210010];
    int cnt,head[maxn],n,m,ki,len[maxn];
    bool exist[maxn];
    inline void add(int x,int y,int d)
    {
        e[++cnt].next=head[x];
        e[cnt].to=y;
        e[cnt].dis=d;
        head[x]=cnt;
    }
    int spfa()
    {
        queue<int> q;
        memset(len,0x3f,sizeof(len));
        q.push(1);
        len[1]=0;
        exist[1]=1;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            exist[u]=0;
            for(int v,i=head[u];i;i=e[i].next)
                if(len[v=e[i].to]>len[u]+e[i].dis)
                {
                    len[v]=len[u]+e[i].dis;
                    if(!exist[v])
                        exist[v]=1,q.push(v);
                }
        }
        int ret=1e9;
        for(int i=1;i<=ki+1;i++)
            ret=min(ret,len[n*i]);
        return ret;
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&ki);
        memset(e,0x3f,sizeof(e));
        for(int x,y,d,i=1;i<=m;i++)
        {
            scanf("%d%d%d",&x,&y,&d);
            for(int j=0;j<=ki;j++)
            {
                add(x+j*n,y+j*n,d),add(y+j*n,x+j*n,d);
                if(j<ki)
                    add(x+j*n,y+(j+1)*n,d/2),add(y+j*n,x+(j+1)*n,d/2);
            }
        }
        printf("%d
    ",spfa());
        return 0;
    }
  • 相关阅读:
    linq 喜悦
    五班二组高级软件测试作业一总结
    五班二组高级软件测试进度报告
    五班二组黑盒测试实践作业进度报告(1)
    五班二组高级软件测试进度报告
    五班二组高级软件测试进度报告
    [ 语文 ] 西游记50~52回阅读笔记
    [ 具体数学 ] 0:前言
    [ 具体数学 ] 3:和式与封闭式
    [ 历史 ] 黄巢起义
  • 原文地址:https://www.cnblogs.com/ivanovcraft/p/9664531.html
Copyright © 2020-2023  润新知