11.6模拟赛

本文解析两道高难度竞赛题,第一题通过二分法求解最大最小值问题,并给出01矩阵转换思路;第二题则针对洛谷P1613跑路问题,运用倍增算法与Floyd算法解决节点间最短路径问题。

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

补坑,这套题太难了= =
t3看都不想看了果断弃疗,这套题思维难度直逼省选,第一题一看见最大的最小值就往二分答案上考虑,首先这道题给了一个矩形,二分答案之后就变成一个01矩阵,然后此题就变成了O(n*m*log(maxw[i])),百分之百的数据范围是10的10次方,除非数据故意卡你否则绝对能过(其实数据卡你也不一定会T)。
附上代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>

using namespace std;
long long int map[1010][1010],a[1010][1010],s[1010],n,m,tim,l,r;
int check(long long int x)
{
    tim++;
    for (int i=1;i<=n;i++)
    {
        int st=0;
        for (int j=1;j<=m;j++)if (a[i][j]>=x)s[++st]=j;
        for (int j=1;j<st;j++)
        for (int k=j+1;k<=st;k++)//转换为01矩阵。
        {
            if (map[s[j]][s[k]]==tim)return 1;
            map[s[j]][s[k]]=tim;
        }
    }
    return 0;
}

int main()
{
    freopen("build.in","r",stdin);
    freopen("build.out","w",stdout);
    cin>>n>>m;
    for (int i=1;i<=n;i++)
    for (int j=1;j<=m;j++)
    {
        scanf("%I64d",&a[i][j]);
        if (r<a[i][j])r=a[i][j];
    }
    for ( long long int x;l<r;(check(x=l+r+1>>1))?l=x:r=x-1);//二分答案
    printf("%I64d",l);
    fclose(stdin);
    fclose(stdout);
    return 0;   
}

第二题也是难啊,是洛谷的P1613跑路,看到2的k次方就应该想到倍增的QAQ,还是这类题目做少了,以后要注意读题= =,其实就是一个倍增问题,一开始先初始化使每两点的距离为INF(其实就是floyd的正常套路啦),然后枚举每个点判断两个点能否用1s到达,如果可以就将两点连上一条边,之后用floyd来处理一遍处理出来每两点之间的距离,从而得出第一个点与第n个点之间的距离,其实代码比较好写,但是思维难度略大。
附代码

#include<cstdio>
#include<iostream>
#define rep(i,x) for (register int i=1;i<=x;i++)
using namespace std; 
int d[60][60],n,m,f[40][60][60],u,v;
int main()
{
    freopen("run.in","r",stdin);
    freopen("run.out","w",stdout);
    cin>>n>>m;
    rep(i,n)rep(j,n)d[i][j]=1<<28;//预处理
    rep(i,m)
    {
        scanf("%d%d",&u,&v);
        f[0][u][v]=d[u][v]=1;//读边,初始化距离为1的点
    }
    rep(k,31)rep(l,n)rep(i,n)rep(j,n)
    {
        if (f[k-1][l][j]+f[k-1][i][l]==2)f[k][i][j]=d[i][j]=1;//处理能够在1s之内到达点
    }
    rep(k,n)rep(i,n)rep(j,n)
    if (d[i][k]+d[k][j]<d[i][j])
    d[i][j]=d[i][k]+d[k][j];//floyd处理一遍
    cout<<d[1][n];//输出答案
    fclose(stdin);
    fclose(stdout);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值