在最近,(两天前)有一场比赛在网上进行,是一场编程邀请赛。这段时间,我就给大家讲一下关于这次比赛的具体内容与答案。
这次讲第一题——核酸检测
题目描述
A. 核酸检测
时间限制:100ms
空间限制:128MB
题目描述
新型冠状病毒疫情爆发!某城市内大量疑似患者被集中到各个隔离点,初期确诊非常困难,专家团队需要依次到这些隔离点去现场指导,为疑似患者进行核酸检测。
城市共有n*(n+1)个隔离点,它们形成了n行n+1列的方阵。我们用(r,c)来表示位于从上到下第r行、从左到右第c列的隔离点。例如,左上角的坐标是(1,1),右下角的坐标是(n,n+1) 。
该城市的交通结构比较特殊,任意两个对角方向的相邻隔离点之间有一条双向通路。
此外,在方阵的边界处有一条顺时针运行的单向地铁环线。
下图是某一个城市的示意图:
专家可以从任意一个隔离点出发,之后你可以沿着道路或乘坐地铁前往其他隔离点。
走过一条道路、乘坐一段地铁都需要1单位时间。在隔离点处进行核酸检测所需的时
间忽略不计。
专家迫切想要知道最少需要多少时间才能完成所有隔离点的核酸检测。请求出最少需
要的时间,以及一条路线。
题目分析
初一看,诶,似乎是搜索的题目耶,那就很简单,直接枚举每一个点。
可是我一做,诶,发现不对劲,似乎这道题不是那么做的。有这几个点我想不出来如何做:
1、这张图中有双向通路,可以往回走!
2、出发点和结束点不一定!所以得要先枚举出发点!
3、可能使用动态规划吗?方程与f怎么设?
对于第三个问题,我想了好久,有好多结果。。。如:
f[i][j]代表从出发点(Oh)到点i,j的最大路径?
所以,这道题一定不能死坑,况且,n<=100,2^100似乎不可能啊!这道题其实在实际考试中,可以通过打表拿到七分(我就是这样的)。下面是测试点的表格:
子任务编号 | 特殊限制 | 分值 |
---|---|---|
1 | n=2 | 7 |
2 | n=3 | 15 |
3 | n<=5 | 29 |
4 | n<=10 | 21 |
5 | n<=100 | 28 |
样例:
输入:
2
输出:
5
1 1
1 2
1 3
2 3
2 2
2 1
样例数据中n=2。
在考场可惜我没想到以下想到的内容,想到了其实简单到爆炸。
ok,接下来,我们研究下样例数据:
样例数据研究
这就是样例给出的额行进路线。这…是不是出题人乱编的啊?天哪,这简直就是让 不让同鞋们发现规律。很好,根据题目中所说的图片,我们也来走一走迷宫。
emmmm,错了。没关系,我们再来!
诶哟,终于成功了!似乎是有规律的耶!大家观察一下:从左下角的点开始,向右上和右下进行,到头来向下,重复刚才的动作,直到头向上再进行…重复执行至最后一行,就可以顺利通过全部的点了!
验证思想
可能有人又要说了,你这方法只是局限于行数为奇数的呀,你这放在欧鼠李就行不通啦!
但是,大家想一想,如果将图“哗啦”一下子翻转,也不就变成了奇数行的吗?(由于一条边是另一条边长度+1)
观察:
这样,轻轻松松将题目变成了模拟题。(做笔记!)此刻,我们就知道,这种图可以一次走完,次数为 次,时间复杂度为 (就是模拟一下)
程序实现
今天的程序很简单啦!!!
#include<iostream>
using namespace std;
int main()
{
int n,x,y;
cin>>n;
cout<<n*(n+1)-1<<endl;
if(n%2==1)
{
cout<<n<<" 1"<<endl;
x=n;y=1; //初始地点初始化
while(x>1)
{
x--;y++; cout<<x<<" "<<y<<endl; //右上
while(y<n+1)
{
x++;y++; cout<<x<<" "<<y<<endl; //右下
x--;y++; cout<<x<<" "<<y<<endl; //右上
}
x++; cout<<x<<" "<<y<<endl; //下
x--;y--; cout<<x<<" "<<y<<endl; //左上
while(y>1)
{
x++;y--; cout<<x<<" "<<y<<endl; //左下
x--;y--; cout<<x<<" "<<y<<endl; //左上
}
x--; cout<<x<<" "<<y<<endl; //上
}
while(y<n+1)
{
y++;
cout<<n<<" "<<n+1<<endl;
}
}
else
{
cout<<n<<" "<<n<<endl;
x=n;y=n+1;
while(y>1)
{
x--;y--; cout<<x<<" "<<y<<endl; //左上
while(x>1)
{
x--;y++; cout<<x<<" "<<y<<endl; //右上
x--;y--; cout<<x<<" "<<y<<endl; //左上
}
y++; cout<<x<<" "<<y<<endl; //右
x++;y--; cout<<x<<" "<<y<<endl; //左下
while(x<n)
{
x++;y++; cout<<x<<" "<<y<<endl; //右下
x++;y--; cout<<x<<" "<<y<<endl; //左下
}
y--; cout<<x<<" "<<y<<endl; //左
}
while(x>1)
{
x--;
cout<<x<<" "<<y<<endl;
}
}
return 0;
}
今天画图就画的好累呀!希望大家能够听懂并学会分析题目的方法~~
对了,附上这次考试的复测地点:
http://115.236.49.52:83/contests