Codeforces Round #719 (Div. 3)
文章目录
- [Codeforces Round #719 (Div. 3)](https://codeforces.com/contest/1520)
- Problem A:[Do Not Be Distracted!](https://codeforces.com/contest/1520/problem/A)
- Problem B:[Ordinary Numbers](https://codeforces.com/contest/1520/problem/B)
- Problem C:[Not Adjacent Matrix](https://codeforces.com/contest/1520/problem/C)
- Problem D:[Same Differences](https://codeforces.com/contest/1520/problem/D)
- Problem E:[Arranging The Sheep](https://codeforces.com/contest/1520/problem/E)
- Problem F1:[Guess the K-th Zero (Easy version)](https://codeforces.com/contest/1520/problem/F1)
- Problem F2:[Guess the K-th Zero (Hard version)](https://codeforces.com/contest/1520/problem/F2)
- Problem G:[To Go Or Not To Go?](https://codeforces.com/contest/1520/problem/G)
Problem A:Do Not Be Distracted!
给 出 一 个 长 度 50 以 内 的 字 符 串 , 连 续 的 一 段 相 同 的 字 符 当 成 一 个 字 符 来 看 如 果 当 前 字 符 以 前 出 现 过 的 话 输 出 " Y E S " , 否 则 输 出 " N O " . 给出一个长度50以内的字符串,连续的一段相同的字符当成一个字符来看\\如果当前字符以前出现过的话输出"YES",否则输出"NO". 给出一个长度50以内的字符串,连续的一段相同的字符当成一个字符来看如果当前字符以前出现过的话输出"YES",否则输出"NO".
做法就是像题意一样模拟,有个变量写错了,还调了一会,太菜了
// Problem: G. To Go Or Not To Go?
// Contest: Codeforces - Codeforces Round #719 (Div. 3)
// URL: https://codeforces.com/contest/1520/problem/G
// Memory Limit: 512 MB
// Time Limit: 3000 ms
/*Love coding and thinking!*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
#define pb push_back
#define mem(f, x) memset(f,x,sizeof(f))
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo2(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
typedef pair<int,int>PII;
typedef pair<long,long>PLL;
typedef long long ll;
const int N=2e5+10;
int n,m,_,t;
int cnt[100];
int main()
{
cin>>t;
while(t--)
{
mem(cnt,0);
string s;
cin>>n;//TM 少读入了
cin>>s;
bool flag=0;
cnt[s[0]-'A']++;
for(int i=1;i<s.size();i++)
{
if(!cnt[s[i]-'A'])
{cnt[s[i]-'A']++;continue;}
if(s[i]-'A'==s[i-1]-'A')continue;
if(cnt[s[i]-'A']&&s[i]-'A'!=s[i-1]-'A')
{
puts("NO");
flag=1;
break;
}
}
// for(int i=0;i<s.size();i++)
// cout<<cnt[s[i]-'A']<" ";
if(!flag)
puts("YES");
}
return 0;
}
Problem B:Ordinary Numbers
判 断 数 1 ∼ n ( 1 < = n < = 1 0 9 ) 中 有 多 少 个 数 是 O r d i n a r y N u m b e r s 如 果 一 个 数 各 位 全 是 相 同 的 则 是 O r d i n a r y N u m b e r s 判断数1\sim n(1<=n<=10^9)中有多少个数是Ordinary Numbers\\ 如果一个数各位全是相同的则是Ordinary Numbers 判断数1∼n(1<=n<=109)中有多少个数是OrdinaryNumbers如果一个数各位全是相同的则是OrdinaryNumbers
明 显 需 要 推 导 出 一 个 数 学 公 式 来 , 容 易 发 现 O r d i n a r y N u m b e r s 数 的 个 数 和 x ( 当 前 考 虑 的 数 ) 的 位 数 有 关 特 判 一 下 n < = 9 的 情 况 , 假 设 x = 122 , 明 显 有 1 9 , 11 99 ( 9 个 ) , 再 判 断 111 这 种 数 字 有 多 少 个 即 可 明显需要推导出一个数学公式来,容易发现Ordinary Numbers数的个数和x(当前考虑的数)的位数有关\\特判一下n<=9的情况,假设x=122,明显有1~9,11~99(9个),再判断111这种数字有多少个即可 明显需要推导出一个数学公式来,容易发现OrdinaryNumbers数的个数和x(当前考虑的数)的位数有关特判一下n<=9的情况,假设x=122,明显有1 9,11 99(9个),再判断111这种数字有多少个即可
// Problem: B. Ordinary Numbers
// Contest: Codeforces - Codeforces Round #719 (Div. 3)
// URL: https://codeforces.com/contest/1520/problem/B
// Memory Limit: 256 MB
// Time Limit: 2000 ms
/*Love coding and thinking!*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
#define pb push_back
#define mem(f, x) memset(f,x,sizeof(f))
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo2(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
typedef pair<int,int>PII;
typedef pair<long,long>PLL;
typedef long long ll;
const int N=2e5+10;
int n,m,_;
int check(int n)
{
int s=0;
while(n)
{
s++;
n/=10;
}
return s;
}
int main()
{
int t;cin>>t;
while(t--)
{
cin>>n;
if(n<=9){cout<<n<<endl;continue;}
int d=check(n);
// cout<<d<<endl;
int sum=0;
sum+=(d-1)*9;
int s=1;
d--;
while(d--)
{
s=1+s*10;
}
// cout<<s<<endl;
sum+=n/s;
cout<<sum<<endl;
}
return 0;
}
Problem C:Not Adjacent Matrix
用 1 ∼ n 2 填 充 一 个 n ∗ n 的 矩 阵 , 满 足 相 邻 格 子 的 数 之 间 差 的 绝 对 值 不 等 于 1 容 易 想 到 奇 数 位 填 123 x , 偶 数 位 x x + 1 x + 2 一 直 填 下 去 就 好 了 , 比 如 3 ∗ 3 的 一 组 解 1 6 2 7 3 8 4 9 5 用1\sim n^2填充一个n*n的矩阵,满足相邻格子的数之间差的绝对值不等于1\\ 容易想到奇数位填1 2 3 x, 偶数位 x x+1 x+2一直填下去就好了,比如3*3的一组解\\ \begin{matrix} 1 & 6 & 2\\ 7 & 3 & 8 \\ 4 & 9 & 5\\ \end{matrix} 用1∼n2填充一个n∗n的矩阵,满足相邻格子的数之间差的绝对值不等于1容易想到奇数位填123x,偶数位xx+1x+2一直填下去就好了,比如3∗3的一组解174639285
// Problem: C. Not Adjacent Matrix
// Contest: Codeforces - Codeforces Round #719 (Div. 3)
// URL: https://codeforces.com/contest/1520/problem/C
// Memory Limit: 256 MB
// Time Limit: 4000 ms
/*Love coding and thinking!*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
#define pb push_back
#define mem(f, x) memset(f,x,sizeof(f))
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo2(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
typedef pair<int,int>PII;
typedef pair<long,long>PLL;
typedef long long ll;
const int N=110;
int n,m,_;
int a[N*N];
int main()
{
cin>>_;
while(_--)
{
cin>>n;
if(n==1)puts("1");
else if(n==2)puts("-1");
else
{
int cnt=1;
for(int i=1;i<=n*n;i+=2,cnt++)
a[i]=cnt;
for(int i=2;i<=n*n;i+=2,cnt++)
a[i]=cnt;
for(int i=1;i<=n*n;i++)
{
printf("%d ",a[i]);
if(i%n==0)puts("");
}
}
}
return 0;
}
Problem D:Same Differences
寻 找 给 定 数 组 中 有 多 少 个 数 对 ( i , j ) 满 足 i < j 并 且 a j − a i = = j − i 1 < = n < = 2 ∗ 1 0 5 , 明 显 扫 两 遍 不 行 , 只 能 O ( N ) , 或 者 O ( N ∗ l o g ( N ) ) a j − a i = = j − i 移 项 有 a j − j = = a i − i , 把 这 个 看 成 一 个 量 , 用 m a p 存 一 下 , 再 组 合 数 算 一 下 就 好 了 寻找给定数组中有多少个数对(i,j)满足i<j 并且 a_j-a_i==j-i\\ 1<=n<=2*10^5,明显扫两遍不行,只能O(N),或者O(N*log(N))\\ a_j-a_i==j-i 移项有 a_j-j==a_i-i,把这个看成一个量,用map存一下, 再组合数算一下就好了 寻找给定数组中有多少个数对(i,j)满足i<j并且aj−ai==j−i1<=n<=2∗105,明显扫两遍不行,只能O(N),或者O(N∗log(N))aj−ai==j−i移项有aj−j==ai−i,把这个看成一个量,用map存一下,再组合数算一下就好了
记得开long long,一开始竟然想用set人傻了
// Problem: D. Same Differences
// Contest: Codeforces - Codeforces Round #719 (Div. 3)
// URL: https://codeforces.com/contest/1520/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
/*Love coding and thinking!*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
#define pb push_back
#define mem(f, x) memset(f,x,sizeof(f))
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo2(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
typedef pair<int,int>PII;
typedef pair<long,long>PLL;
typedef long long ll;
const int N=2e5+10;
int n,m,_;
int a[N];
map<int,ll>mp;
int main()
{
cin>>_;
while(_--)
{
// set<int>st;
mp.clear();
cin>>n;
for(int i=1;i<=n;i++)//min 1-2e5
scanf("%d",&a[i]),a[i]-=i,mp[a[i]]++;
// st[a[i]]++;
ll sum=0;
// for(int i=0;i<n;i++)
// cout<<a[i]<<" ";
// puts("");
// for(int i=0;i<n;i++)
// cout<<St[a[i]]<<" ";
for(auto c:mp)
{
ll d=c.second;
if(d>=2)
sum+=d*(d-1)/2;
}
cout<<sum<<endl;
}
return 0;
}
Problem E:Arranging The Sheep
.
表示空地,*
表示🐏,每次可以将🐏向左或者向右移动一位,对于给定的序列,询问最少的操作步数,使得所有的🐏最后都排成一排,两两紧挨着。类似..***.
货 舱 选 址 的 变 形 题 , 有 点 意 思 , 但 是 不 难 , 比 如 : 货舱选址的变形题,有点意思,但是不难,比如: 货舱选址的变形题,有点意思,但是不难,比如:
*.*...*.**
考虑第二个 * 和第三个 * ,他们之间可以相互靠近,那他们两者的距离要怎么定义呢?
直接用下标的差相减就是货仓选址了,通过.
的累加,定义距离,把*
的权值映射成0 1 4 5 5,然后中位数
// Problem: E. Arranging The Sheep
// Contest: Codeforces - Codeforces Round #719 (Div. 3)
// URL: https://codeforces.com/contest/1520/problem/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
/*Love coding and thinking!*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
#define pb push_back
#define mem(f, x) memset(f,x,sizeof(f))
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo2(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
typedef pair<int,int>PII;
typedef pair<long,long>PLL;
typedef long long ll;
const int N=2e5+10;
int n,m,_;
void solve()
{
vector<int>c;
int tot=0;
cin>>n;
string s;cin>>s;
for(char a:s)
{
if(a=='.')tot++;
else c.pb(tot);
}
//变形的货仓选址,中间花费的距离不是几何距离,还是有多少个
//相隔着的点,因为两个点,可以互相靠近
if(c.empty()){puts("0");return ;}
sort(c.begin(),c.end());
ll sum=0;
int m=c[c.size()/2];
for(auto k:c)
sum+=abs(k-m);
cout<<sum<<endl;
}
int main()
{
cin>>_;
while(_--)
solve();
return 0;
}
Problem F1:Guess the K-th Zero (Easy version)
之前做cf的时候也见过交互题,没补过,算是第一次正式写这种题,其实交互题应该挺套路的
给 定 n 个 0 、 1 数 , 他 们 是 隐 藏 的 , 给 定 k 表 示 询 问 第 k 个 0 的 下 标 ( 从 1 开 始 编 号 ) 用 户 的 程 序 每 次 通 过 询 问 " ? l r " 得 到 电 脑 的 回 答 a n s , a n s 表 示 [ l , r ] 内 1 的 个 数 通 过 不 超 过 20 次 询 问 最 后 给 出 第 k 个 0 的 下 标 给定n个0、1数,他们是隐藏的,给定k表示询问第k个0的下标(从1开始编号)\\ 用户的程序每次通过询问"? \quad l \quad r"得到电脑的回答ans,ans表示[l,r]内1的个数\\ 通过不超过20次询问最后给出第k个0的下标 给定n个0、1数,他们是隐藏的,给定k表示询问第k个0的下标(从1开始编号)用户的程序每次通过询问"?lr"得到电脑的回答ans,ans表示[l,r]内1的个数通过不超过20次询问最后给出第k个0的下标
应该算是二分的裸题,但是写不对就离谱(太菜了吧,之前还专门做过二分专题的),给一道交互题模板题目
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{int l=1,r=1000000000;
for(;l<r;)
{
int mid=l+r+1>>1;
cout<<mid<<endl;
int x;cin>>x;
if(x==0)return 0;
else if(x==-1)
l=mid;
else
r=mid-1;
}
cout<<l<<endl;//还是在某位大佬的帮助下改的,洛谷好棒
//如果待查询的是1,一直返回1,最后r=3,mid=2,r=mid-1,r=1,l=1,mid=1,查看直接退出,没有输出1。
return 0;
}
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{int l=0,r=1000000000;
for(;l<r;)
{
int mid=l+r+1>>1;
cout<<mid<<endl;
int x;cin>>x;
if(x==0)return 0;
else if(x==-1)
l=mid;
else
r=mid-1;
}
//cout<<l<<endl;把l放左边一点,就不需要特判了,不错,y总板子就是边界又可能会有点问题
return 0;
}
这题看了下b站有视频讲解
逻辑:如果[1,cur]中有k个0
[1,cur-1]中有k-1个0,那么第cur个位置就是第k个0
将询问模板话
int query(int l,int r)
{
cout<<"? "<<l<<" "<<r<<"\n";
//经过实际测试,cf上不能使用cout<<endl;来清空缓冲区,只能用
//fflush(stdout)否则会WA,但是洛谷就可以用cout<<endl;来清空
fflush(stdout);
int x;cin>>x;
return x;
}
bool check(int cur)//[1,cur]中0的个数是否大于k
{
if(cur-query(1,cur)>=k)return 1;
return 0;
}
#define mid ((l+r)>>1)
int main()
{
cin>>n>>k;cin>>k;
int l=1,r=n;
while(l+1<r)
{
if(check(mid))r=mid;
else l=mid;
}
if(check(l))cout<<"! "<<l<<endl;
else cout<<"! "<<r<<endl;
return 0;
}
自己的代码
// Problem: F1. Guess the K-th Zero (Easy version)
// Contest: Codeforces - Codeforces Round #719 (Div. 3)
// URL: https://codeforces.com/contest/1520/problem/F1
// Memory Limit: 256 MB
// Time Limit: 1000 ms
/*Love coding and thinking!*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
#define pb push_back
#define mem(f, x) memset(f,x,sizeof(f))
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo2(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
typedef pair<int,int>PII;
typedef pair<long,long>PLL;
typedef long long ll;
const int N=2e5+10;
int n,t,k,m,_;
//交互题
int query(int l,int r)//将查询封装
{
/*有一些坑点,题目得输出是两个换行
经过测试如果输出endl或者'\n'再使用 fflush(stdout)清空没有问题,但是输出两个换行会直接WA,就很离谱
*/
cout<<"? "<<l<<" "<<r<<'\n'<<endl;
fflush(stdout);
int x;cin>>x;return x;
}
/*
基本二分裸题了
[1,x] k个0
[1,x-1] k-1个0 那么x就是第k个0
*/
bool check(int cur)//查询[1,cur]
{
if(cur-query(1,cur)>=k)return 1;
return 0;
}
int main()
{
cin>>n>>k>>k;
int l=1,r=n;
while(l+1<r)
{
int mid=l+r>>1;
//不会写的话就先写上模板,再填充
if(check(mid))//还能缩小范围
r=mid;
else
l=mid;;
}
// cout<<l<<" "<<r<<endl;
if(check(l))cout<<"! "<<l<<endl;
else
cout<<"! "<<r<<endl;
return 0;
}
Problem F2:Guess the K-th Zero (Hard version)
Problem G:To Go Or Not To Go?
给 一 个 n ∗ m 的 带 权 地 图 和 每 步 的 权 值 w , − 1 表 示 不 能 走 , 0 表 示 需 要 w 权 值 走 到 相 邻 的 点 其 他 的 值 表 示 虫 洞 , 图 中 任 意 的 虫 洞 都 能 互 相 达 到 , 花 费 虫 洞 上 权 值 的 时 间 . 给一个n*m的带权地图和每步的权值w ,-1表示不能走,0表示需要w权值走到相邻的点\\其他的值表示虫洞,图中任意的虫洞都能互相达到,花费虫洞上权值的时间. 给一个n∗m的带权地图和每步的权值w,−1表示不能走,0表示需要w权值走到相邻的点其他的值表示虫洞,图中任意的虫洞都能互相达到,花费虫洞上权值的时间.
因 为 有 不 连 通 的 情 况 , 需 要 从 起 点 和 终 点 进 行 两 次 b f s , 统 计 出 两 个 d 数 组 都 不 使 用 虫 洞 , d [ 0 ] [ i ] [ j ] 表 示 从 起 点 到 ( i , j ) 需 要 的 最 短 路 径 同 理 有 d [ 1 ] [ i ] [ j ] , 那 么 对 于 每 个 点 d i s = d [ 0 ] [ i ] [ j ] + d [ 1 ] [ i ] [ j ] 表 示 不 使 用 虫 洞 的 条 件 下 互 通 的 最 短 距 离 . 扫 一 遍 矩 阵 , 重 新 更 新 一 下 d 数 组 , 如 果 该 点 的 值 不 是 − 1 并 且 不 是 0 从 d [ 0 ] 和 d [ 1 ] 中 挑 出 两 个 最 短 的 距 离 和 作 为 使 用 虫 洞 的 条 件 下 的 最 短 距 离 比 较 大 小 输 出 因为有不连通的情况,需要从起点和终点进行两次bfs,统计出两个d数组\\都不使用虫洞,d[0][i][j]表示从起点到(i,j) 需要的最短路径\\同理有d[1][i][j],那么对于每个点dis=d[0][i][j]\ +\ d[1][i][j]表示不使用虫洞的条件下互通的最短距离.\\ 扫一遍矩阵,重新更新一下d数组,如果该点的值不是 -1 并且不是\ 0\\从d[0]和d[1]中挑出两个最短的距离和作为使用虫洞的条件下的最短距离\\比较大小输出 因为有不连通的情况,需要从起点和终点进行两次bfs,统计出两个d数组都不使用虫洞,d[0][i][j]表示从起点到(i,j)需要的最短路径同理有d[1][i][j],那么对于每个点dis=d[0][i][j] + d[1][i][j]表示不使用虫洞的条件下互通的最短距离.扫一遍矩阵,重新更新一下d数组,如果该点的值不是−1并且不是 0从d[0]和d[1]中挑出两个最短的距离和作为使用虫洞的条件下的最短距离比较大小输出
记得开long long ,用0x3f3f3f3f3f3f3f3f来赋值,否则WA113,还有就是如果比某个无穷大的话输出-1表示无法到达
// Problem: G. To Go Or Not To Go?
// Contest: Codeforces - Codeforces Round #719 (Div. 3)
// URL: https://codeforces.com/contest/1520/problem/G
// Memory Limit: 512 MB
// Time Limit: 3000 ms
/*Love coding and thinking!*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
#define pb push_back
#define mem(f, x) memset(f,x,sizeof(f))
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo2(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
typedef pair<int,int>PII;
typedef pair<long,long>PLL;
typedef long long ll;
const int N=2e3+10;
int g[N][N],n,m;
ll w;
ll dis[2][N][N];//512MB
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
bool st[N][N];
void bfs_1()
{
mem(st,0);
mem(dis,0x3f);
// for(int i=1;i<=n;i++)
// for(int j=1;j<=m;j++)dis[0][i][j]=dis[1][i][j]=0x3f3f3f3f;
dis[0][1][1]=0;
queue<PII>que;
que.push({1,1});
st[1][1]=1;
while(que.size())
{
auto t=que.front();
que.pop();
for(int i=0;i<4;i++)
{
int X=t.first+dx[i];
int Y=t.second+dy[i];
if(X<1||X>n||Y<1||Y>m)continue;
if(st[X][Y]||g[X][Y]==-1)continue;
st[X][Y]=1;
que.push({X,Y});
if(dis[0][X][Y]>dis[0][t.first][t.second]+w)
dis[0][X][Y]=dis[0][t.first][t.second]+w;
}
}
}
void bfs_2()
{
mem(st,0);
// for(int i=1;i<=n;i++)
// for(int j=1;j<=m;j++)dis[1][i][j]=0x3f3f3f3f;//dis开成1了,人傻了
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++)
// cout<<dis[1][i][j]<<" ";
// puts("");
// }
dis[1][n][m]=0;
queue<PII>que;
que.push({n,m});
st[n][m]=1;
while(que.size())
{
auto t=que.front();
que.pop();
for(int i=0;i<4;i++)
{
int X=t.first+dx[i];
int Y=t.second+dy[i];
if(X<1||X>n||Y<1||Y>m)continue;
if(st[X][Y]||g[X][Y]==-1)continue;
st[X][Y]=1;
que.push({X,Y});
if(dis[1][X][Y]>dis[1][t.first][t.second]+w)
dis[1][X][Y]=dis[1][t.first][t.second]+w;
}
}
}
int main()
{
cin>>n>>m>>w;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&g[i][j]);
bfs_1();
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++)
// cout<<dis[0][i][j]<<" ";
// puts("");
// }
// debug(dis[0][1][1]);
bfs_2();
// cout<<dis[0][1][1]<<endl;
// puts("------------------------");
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++)
// cout<<dis[1][i][j]<<" ";
// puts("");
// }
ll sum=0x3f3f3f3f3f3f3f3f;// 不使用虫洞的条件下,最小的花费
ll minn_1,minn_2;
minn_1=minn_2=0x3f3f3f3f3f3f3f3f;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
sum=min(sum,dis[0][i][j]+dis[1][i][j]);
}
// debug(sum);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(g[i][j]!=-1&&g[i][j]!=0)
{
dis[0][i][j]+=g[i][j];
dis[1][i][j]+=g[i][j];
minn_1=min(minn_1,dis[0][i][j]);
minn_2=min(minn_2,dis[1][i][j]);
}
}
}
sum=min(sum,minn_1+minn_2);
if(sum>0x3f3f3f3f3f3f3f3f/2)
puts("-1");
else
cout<<sum;
return 0;
}