2021-10-19

这是一个关于图论和动态规划的问题。给定一个国家的交通网络,每两个城市间存在一条路径且每条边都有费用,费用与携带物品的数量和天数成正比。目标是确定在有限预算下,从起点S到终点T能运输的最大物品数量。通过Floyd-Warshall算法求出所有城市间的最短路径,然后使用二分查找和动态规划方法计算最大物品数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

K

题目链接

欢欢一直在研究狂热的编程问题。然而,今天他决定让自己休息一下,去一个美丽的国家旅行。因此,出现了另一个问题。

全国共有n个城市。有m 条双向道路,每条道路都直接连接两个不同的城市。由于该国拥有稳固的交通系统,因此每两个城市之间总会有一条路径连接。

欢欢到了S市,想把尽可能多的物品运到T市。每天他都会走过一条路。每经过一条路,都要付出一定的代价。根据政策,费用取决于您携带的物品数量和您进入该国的天数。更准确地说,每条道路的费用是k d,其中k 是黄欢要携带的物品数量,d 是他入境的天数。

例如,黄环到达ar市1 ,瞄准市3 。他选择的路径是1->2->3 携带2 个 物品。那么路1->2的费用 将是2 1 和路2->3的费用 将是2 2 . 所以总费用是2 1 +2 2 =6

现在,您的任务是帮助他决定他可以携带的最大物品数量,因为他的预算有限。

不过,欢欢准备在未来多次出差。将为您提供完全Q 查询。

输入描述:

第一行包含两个整数 n,m (1≤n≤100, m≤(n(n+1)/2)),其中 n 是城市数量,m 是道路数量。(保证每两个城市相连,没有两条道路直接连接同一两个城市。)
然后,将m行跟随,第i个 线包含两个整数ui,vi (1≤ui,vi≤N,ui≠vi),表示第i个 路连接城市ui 和vi。
接下来的几行包含一个整数 q(1≤Q≤10 5 ),表示查询的次数。
然后是Q行,每行包含3个整数S、T、B(1≤S,T≤n,0≤B≤1e9),分别表示到达的城市、目标城市和预算。

输出描述:

对于每个查询,打印一个整数作为欢欢从城市 S 到 T 可以携带的最大项目。

示例1

输入

3 2
1 2
2 3
3
1 2 5
1 3 5
2 3 2

输出

5
1
2

思路

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=1e9;
const int N=110;
int dis[N][N];
int main()
{
    int n,m;int x,y;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
            dis[i][j]=0x3f3f3f3f;
    }


    for(int i=0;i<m;i++)
    {
        cin>>x>>y;
        dis[x][y]=dis[y][x]=1;//表示x,y直接连接
    }
    for(int i=1;i<=n;i++)
        dis[i][i]=0;
        //弗洛伊德
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(dis[i][j]>dis[i][k]+dis[k][j])
                    dis[i][j]=dis[i][k]+dis[k][j];
          

    int q;int s,t;ll b;int distance;
    ll sum;
    cin>>q;
    for(int i=0;i<q;i++)
    {
        cin>>s>>t>>b;
        distance=dis[s][t];
        int l=1,r=b;
        while(l<r)
        {
            sum=0;
            int mid=(l+r+1)/2;
            for(int j=1;j<=distance;j++)
            {
                sum+=pow(mid,j);
                if(sum>b)
                    break;
            }
            if(sum<=b)
                l=mid;
            else
                r=mid-1;
        }
        sum=0;
        for(int j=1;j<=distance;j++)
        {
            sum+=pow(l,j);
        }
        if(sum<=b)
            cout<<l<<endl;
        else
            cout<<l-1<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值