Codeforces Round #719 (Div. 3) 解题思路

Codeforces Round #719 (Div. 3)

A - Do Not Be Distracted!

题意

给定长度为 n n n的仅包含大写字母的字符串 S S S

问相同的字符是否只连续出现了一段

思路

直接遍历,每找到一段就标记一次,检查当前段是否已经被标记过即可

//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/hash_policy.hpp>
#include<bits/stdc++.h>
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
#define all(a) (a).begin(),(a).end()
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define eb emplace_back
using namespace std;
//using namespace __gnu_pbds;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-12;
const double PI=acos(-1.0);
const ll mod=998244353;
mt19937 mt19937random(std::chrono::system_clock::now().time_since_epoch().count());
ll getRandom(ll l,ll r){return uniform_int_distribution<ll>(l,r)(mt19937random);}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qmul(ll a,ll b){ll r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;}
ll qpow(ll a,ll n){ll r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
ll qpow(ll a,ll n,ll p){ll r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;}



void solve()
{
    int n;
    string s;
    cin>>n>>s;
    int v[26]={0};
    repp(i,0,n)
    {
        char c=s[i];
        if(!v[c-'A'])
        {
            v[c-'A']=1;
            int j=i;
            while(j<n&&s[j]==s[i])
                j++;
            i=j-1;
        }
        else
        {
            cout<<"NO\n";
            return;
        }
    }
    cout<<"YES\n";
}
int main()
{
    closeSync;
    multiCase
    {
        solve();
    }
    return 0;
}


B - Ordinary Numbers

题意

定义一个数字是ordinary的,当且仅当它每一位上的数字都相同

1 1 1 n n n中有多少个数字是ordinary

思路

1 0 9 10^9 109的范围内仅存在 9 ∗ 9 = 81 9*9=81 99=81个合法数字,直接预处理后二分即可

//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/hash_policy.hpp>
#include<bits/stdc++.h>
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
#define all(a) (a).begin(),(a).end()
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define eb emplace_back
using namespace std;
//using namespace __gnu_pbds;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-12;
const double PI=acos(-1.0);
const ll mod=998244353;
mt19937 mt19937random(std::chrono::system_clock::now().time_since_epoch().count());
ll getRandom(ll l,ll r){return uniform_int_distribution<ll>(l,r)(mt19937random);}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qmul(ll a,ll b){ll r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;}
ll qpow(ll a,ll n){ll r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
ll qpow(ll a,ll n,ll p){ll r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;}

vector<ll> vec;

void init()
{
    rep(i,1,9) //枚举数字
    {
        ll v=0;
        rep(j,1,9) //枚举位数
        {
            v=v*10+i;
            vec.pb(v);
        }
    }
    sort(all(vec));
}
void solve()
{
    int n;
    cin>>n;
    cout<<(upper_bound(all(vec),n)-vec.begin())<<'\n';
}
int main()
{
    closeSync;
    init();
    multiCase
    {
        solve();
    }
    return 0;
}


C - Not Adjacent Matrix

题意

构造一个 n × n n\times n n×n的矩阵,使得相邻两个数的差值 > 1 \gt 1 >1,且 1 1 1 n 2 n^2 n2内每个数都在矩阵中出现一次

思路

仅在 n = 2 n=2 n=2时不存在解

其余情况,可以都沿着主对角线方向按顺序放置

主要思路可看下图,按数字顺序放置

pic1

//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/hash_policy.hpp>
#include<bits/stdc++.h>
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
#define all(a) (a).begin(),(a).end()
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define eb emplace_back
using namespace std;
//using namespace __gnu_pbds;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-12;
const double PI=acos(-1.0);
const ll mod=998244353;
mt19937 mt19937random(std::chrono::system_clock::now().time_since_epoch().count());
ll getRandom(ll l,ll r){return uniform_int_distribution<ll>(l,r)(mt19937random);}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qmul(ll a,ll b){ll r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;}
ll qpow(ll a,ll n){ll r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
ll qpow(ll a,ll n,ll p){ll r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;}

int a[105][105];

void solve()
{
    int n;
    cin>>n;
    if(n==1)
    {
        a[1][1]=1;
    }
    else if(n==2)
    {
        cout<<"-1\n";
        return;
    }
    else
    {
        int cur=0;
        rep(i,1,n) //主对角线
            a[i][i]=++cur;
        rep(i,2,n)
        {
            for(int x=1,y=i;y<=n;x++,y++) //主对角线右上方
                a[x][y]=++cur;
            for(int x=i,y=1;x<=n;x++,y++) //主对角线左下方
                a[x][y]=++cur;
        }
    }
    rep(i,1,n)
        rep(j,1,n)
            cout<<a[i][j]<<(j==n?'\n':' ');
}
int main()
{
    closeSync;
    multiCase
    {
        solve();
    }
    return 0;
}


D - Same Differences

题意

给定一个数列 { a } \{a\} {a}

询问存在多少二元组 ( i , j ) (i,j) (i,j),满足 i < j i\lt j i<j a j − a i = j − i a_j-a_i=j-i ajai=ji

思路

a j − a i = j − i a_j-a_i=j-i ajai=ji看作 a j − j = a i − i a_j-j=a_i-i ajj=aii

按顺序遍历每个位置的数

map存储出现的 a j − j a_j-j ajj的次数作为当前位置 j j j所匹配上的 i i i的数量即可

//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/hash_policy.hpp>
#include<bits/stdc++.h>
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
#define all(a) (a).begin(),(a).end()
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define eb emplace_back
using namespace std;
//using namespace __gnu_pbds;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-12;
const double PI=acos(-1.0);
const ll mod=998244353;
mt19937 mt19937random(std::chrono::system_clock::now().time_since_epoch().count());
ll getRandom(ll l,ll r){return uniform_int_distribution<ll>(l,r)(mt19937random);}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qmul(ll a,ll b){ll r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;}
ll qpow(ll a,ll n){ll r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
ll qpow(ll a,ll n,ll p){ll r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;}

int a[200050];

void solve()
{
    map<int,int> mp;
    int n;
    cin>>n;
    ll ans=0;
    rep(i,1,n)
    {
        cin>>a[i];
        ans+=mp[a[i]-i];
        mp[a[i]-i]++;
    }
    cout<<ans<<'\n';
}
int main()
{
    closeSync;
    multiCase
    {
        solve();
    }
    return 0;
}


E - Arranging The Sheep

题意

给定一个字符串 S S S,仅包含字符 . . . ∗ * 分别表示空地和绵羊

每次操作可以将任意一只绵羊往左或者往右移动一格,只要目标位置存在且为空地

要求将所有绵羊弄到一起(任意两只绵羊间不能有空地)

问最小的操作数

思路

s u m l [ i ] suml[i] suml[i]表示将初始状态的 i i i左侧的所有绵羊全部向右移动到 i i i(且往左排列)所需要的最小操作数

同理, s u m r [ i ] sumr[i] sumr[i]表示将初始状态的 i i i右侧的所有绵羊全部向左移动到 i i i(且往右排列)所需要的最小操作数

以预处理 s u m l suml suml为例,从左向右遍历字符串 S S S

  • 如果位置 i i i空地,那么将左侧所有羊全部移动到 i i i点(且往左排列)的操作数,就是将左侧所有羊全部移动到 i − 1 i-1 i1点(且往左排列)后,再依次将 c n t l [ i ] cntl[i] cntl[i]只羊向右移动一格到 i i i点(且往左排列),故 s u m l [ i ] = s u m l [ i − 1 ] + c n t l [ i ] suml[i]=suml[i-1]+cntl[i] suml[i]=suml[i1]+cntl[i] c n t l [ i ] cntl[i] cntl[i]表示初始状态下 i i i点左侧的绵羊数量

  • 如果位置 i i i绵羊,如果此前已经将 i − 1 i-1 i1点左侧所有羊全部移动到 i − 1 i-1 i1点(且往左排列)了的话,这一步转移就不需要进行移动,即 s u m l [ i ] = s u m l [ i − 1 ] suml[i]=suml[i-1] suml[i]=suml[i1],注意此时 c n t l [ i ] = c n t l [ i − 1 ] + 1 cntl[i]=cntl[i-1]+1 cntl[i]=cntl[i1]+1

预处理 s u m r sumr sumr同理,从右向左遍历即可

最后,枚举 1 1 1 n n n所有位置 p p p,表示将 p p p点左右两侧所有羊都移动到 p p p点(向左右排列),直接维护答案取最小值即可

a n s = m i n { s u m l [ p − 1 ] + s u m r [ p + 1 ] + t } ans=min\{suml[p-1]+sumr[p+1]+t\} ans=min{suml[p1]+sumr[p+1]+t}

t t t表示如果 p p p点刚开始不是只羊的话,还需要将某一侧的羊再依次移动一格,即 t = m i n ( c n t l [ i ] , c n t r [ i ] ) t=min(cntl[i],cntr[i]) t=min(cntl[i],cntr[i])

如果 p p p点刚开始已经是只羊, t = 0 t=0 t=0

//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/hash_policy.hpp>
#include<bits/stdc++.h>
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
#define all(a) (a).begin(),(a).end()
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define eb emplace_back
using namespace std;
//using namespace __gnu_pbds;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-12;
const double PI=acos(-1.0);
const ll mod=998244353;
mt19937 mt19937random(std::chrono::system_clock::now().time_since_epoch().count());
ll getRandom(ll l,ll r){return uniform_int_distribution<ll>(l,r)(mt19937random);}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qmul(ll a,ll b){ll r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;}
ll qpow(ll a,ll n){ll r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
ll qpow(ll a,ll n,ll p){ll r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;}

char s[1000050];
ll cntl[1000050],cntr[1000050];
ll suml[1000050],sumr[1000050];

void solve()
{
    int n;
    cin>>n>>s+1;
    
    cntl[0]=0;
    suml[0]=0;
    rep(i,1,n)
    {
        if(s[i]=='*')
        {
            cntl[i]=cntl[i-1]+1;
            suml[i]=suml[i-1];
        }
        else
        {
            cntl[i]=cntl[i-1];
            suml[i]=suml[i-1]+cntl[i];
        }
    }
    
    cntr[n+1]=0;
    sumr[n+1]=0;
    per(i,n,1)
    {
        if(s[i]=='*')
        {
            cntr[i]=cntr[i+1]+1;
            sumr[i]=sumr[i+1];
        }
        else
        {
            cntr[i]=cntr[i+1];
            sumr[i]=sumr[i+1]+cntr[i];
        }
    }
    
    ll ans=LINF;
    rep(i,1,n)
    {
        ll ansd=suml[i-1]+sumr[i+1];
        if(s[i]=='.')
            ansd+=min(cntl[i],cntr[i]);
        ans=min(ans,ansd);
    }
    cout<<ans<<'\n';
}
int main()
{
    closeSync;
    multiCase
    {
        solve();
    }
    return 0;
}


F1 - Guess the K-th Zero (Easy version)

题意

现有一个长度为 n ≤ 2 ⋅ 1 0 5 n\le 2\cdot 10^5 n2105 01 01 01序列, t = 1 t=1 t=1

每次你可以输出 ?   l   r ?\ l\ r ? l r来查询 [ l , r ] [l,r] [l,r]的区间和,最多查询 20 20 20

要求你找到第 k k k 0 0 0的下标是多少(从 1 1 1开始)

思路

直接二分即可,维护一个可行区间 [ l , r ] [l,r] [l,r],初始 l = 1 , r = n l=1,r=n l=1,r=n

每次查询 [ l , m i d ] [l,mid] [l,mid],区间长度为 m i d − l + 1 mid-l+1 midl+1,查询的返回值 r e s res res即代表着区间中 1 1 1的个数

m i d − l + 1 − r e s mid-l+1-res midl+1res即区间内 0 0 0的个数

如果 m i d − l + 1 − r e s < k mid-l+1-res\lt k midl+1res<k,即区间内 0 0 0的个数小于待查找的 0 0 0的位置,此时将 l = m i d + 1 l=mid+1 l=mid+1来缩小维护的可行区间,且让 k − = m i d − l + 1 − r e s k-=mid-l+1-res k=midl+1res,表示在当前维护的区间中我们只需要找到第 k − ( m i d − l + 1 − r e s ) k-(mid-l+1-res) k(midl+1res) 0 0 0的下标即可

如果 m i d − l + 1 − r e s ≥ k mid-l+1-res\ge k midl+1resk,则表示第 k k k 0 0 0在查询的 [ l , m i d ] [l,mid] [l,mid]区间内,此时让 r = m i d r=mid r=mid即可

直到 l = = r l==r l==r,输出即可,查询次数为 log ⁡ n ≤ 20 \log n\le 20 logn20

//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/hash_policy.hpp>
#include<bits/stdc++.h>
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
#define all(a) (a).begin(),(a).end()
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define eb emplace_back
using namespace std;
//using namespace __gnu_pbds;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-12;
const double PI=acos(-1.0);
const ll mod=998244353;
mt19937 mt19937random(std::chrono::system_clock::now().time_since_epoch().count());
ll getRandom(ll l,ll r){return uniform_int_distribution<ll>(l,r)(mt19937random);}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qmul(ll a,ll b){ll r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;}
ll qpow(ll a,ll n){ll r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
ll qpow(ll a,ll n,ll p){ll r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;}

int main()
{
    int n,t,k;
    scanf("%d%d%d",&n,&t,&k);
    
    int T=20;
    int l=1,r=n;
    while(T--)
    {
        int m=(l+r)>>1;
        int len=m-l+1;
        
        printf("? %d %d\n",l,m);
        fflush(stdout);
        
        int res;
        scanf("%d",&res);
        
        int cnt=len-res;
        
        if(cnt<k)
        {
            k-=cnt;
            l=m+1;
        }
        else
            r=m;
        
        if(l==r)
        {
            printf("! %d\n",l);
            break;
        }
    }
    return 0;
}


F2 - Guess the K-th Zero (Hard version)

题意


思路

不会了明天补……



G - To Go Or Not To Go?

题意

给定一张 n × m n\times m n×m的图,起点为 ( 1 , 1 ) (1,1) (1,1),终点为 ( n , m ) (n,m) (n,m)

每个点都有一个值, − 1 -1 1表示不可走, 0 0 0表示可走,其余值表示可走且存在一个花费为 a i , j a_{i,j} ai,j的传送器

行走只能向上下左右四个方向走,每走一步花费为 w w w

使用传送器可以立即传送到任意一个其它传送器的位置上,花费为两个传送器的 a i , j a_{i,j} ai,j之和

问从起点走到终点的最小花费,不存在输出 − 1 -1 1

思路

从起点搜一次到每个可走到的点的最短距离存在 d i s 1 dis1 dis1

从终点搜一次到每个可走到的点的最短距离存在 d i s 2 dis2 dis2

由于可以任意传送,所以如果使用传送器的话肯定只使用一次

所以 d i s 1 [ i ] [ j ] + a [ i ] [ j ] dis1[i][j]+a[i][j] dis1[i][j]+a[i][j]就可以表示从起点走到 ( i , j ) (i,j) (i,j)并使用了这个传送器的花费(如果存在传送器)

同理 d i s 2 [ i ] [ j ] + a [ i ] [ j ] dis2[i][j]+a[i][j] dis2[i][j]+a[i][j]就可以表示从 ( i , j ) (i,j) (i,j)走到终点并使用了这个传送器的花费(如果存在传送器)

维护上面两个的最小值,相加后再与不使用任何传送器的情况(即 d i s 1 [ n ] [ m ] dis1[n][m] dis1[n][m] d i s 2 [ 1 ] [ 1 ] dis2[1][1] dis2[1][1])取小输出即可

注意不存在的情况输出 − 1 -1 1

//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/hash_policy.hpp>
#include<bits/stdc++.h>
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
#define all(a) (a).begin(),(a).end()
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define eb emplace_back
using namespace std;
//using namespace __gnu_pbds;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-12;
const double PI=acos(-1.0);
const ll mod=998244353;
mt19937 mt19937random(std::chrono::system_clock::now().time_since_epoch().count());
ll getRandom(ll l,ll r){return uniform_int_distribution<ll>(l,r)(mt19937random);}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qmul(ll a,ll b){ll r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;}
ll qpow(ll a,ll n){ll r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
ll qpow(ll a,ll n,ll p){ll r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;}

int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};

int n,m,w;
int mp[2050][2050];
vector<P> vec;
ll dis1[2050][2050],dis2[2050][2050];

inline bool prim(int x,int y)
{
    return x>0&&y>0&&x<=n&&y<=m;
}

void bfs(int stx,int sty,ll dis[2050][2050])
{
    rep(i,1,n)
        rep(j,1,m)
            dis[i][j]=LINF;
    dis[stx][sty]=0;
    queue<P> q;
    q.push(P(stx,sty));
    while(!q.empty())
    {
        P pd=q.front();
        q.pop();
        int &x=pd.first,&y=pd.second;
        rep(i,0,3)
        {
            int px=dx[i]+x,py=dy[i]+y;
            if(prim(px,py)&&mp[px][py]!=-1&&dis[px][py]>dis[x][y]+w)
            {
                dis[px][py]=dis[x][y]+w;
                q.push(P(px,py));
            }
        }
    }
}

void solve()
{
    cin>>n>>m>>w;
    rep(i,1,n)
        rep(j,1,m)
            cin>>mp[i][j];
    
    bfs(1,1,dis1);
    bfs(n,m,dis2);
    
    ll tmp1=LINF,tmp2=LINF;
    rep(i,1,n)
        rep(j,1,m)
        {
            if(mp[i][j]<=0)
                continue;
            tmp1=min(tmp1,dis1[i][j]+mp[i][j]);
            tmp2=min(tmp2,dis2[i][j]+mp[i][j]);
        }
    ll ans=min(tmp1+tmp2,dis1[n][m]);
    if(ans>=LINF)
        ans=-1;
    cout<<ans<<'\n';
}
int main()
{
    closeSync;
    //multiCase
    {
        solve();
    }
    return 0;
}


https://www.cnblogs.com/stelayuri/p/14733568.html


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值