在最近,(兩天前)有一場比賽在網上進行,是一場編程邀請賽。這段時間,我就給大家講一下關於這次比賽的具體內容與答案。
這次講第一題——核酸檢測
題目描述
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