【考題題解】NOIP模擬賽Day1
noip模擬題Day1
1. 水水の題
[問題描述]
嗯……水水的題。 ti。梯。電梯? emmmmm……
那麼,有一座電梯,它上升一層需要 6 秒鐘,下降一層需要 4 秒鐘,如果
要讓它停下,它會停 5 秒鐘。
現在告訴你,它要按順序到達然後停靠的 N 個樓層,求它需要的時間。
電梯開始在 0 層,樓梯共有 100 層。
[輸入格式]
輸入包含 N+1 行。
第一行為 N,接下來的 N 行是它 N 個停靠的樓層。
[輸出格式]
輸出包含一行。
第一行一個整數, 為所需要的時間。。
[樣例輸入]
3 2 3 1
[樣例輸出]
41
[樣例說明]
NULL
[資料規模與約定]
N<=50。
題解:
直接模擬,上升即為層數的差值乘上6加上5,下降即為層數的差值乘上4加上5。
CODE
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100
int a[MAXN];
int n,ans=0;
void read(int &readnum)
{
int s=0,w=1;char c=getchar();
while (c<'0' || c>'9') {if (c=='-') w= -1;c=getchar();}
while (c>='0' && c<='9') s=s*10+c-48,c=getchar();
readnum=s*w;
}
int main()
{
freopen("ti.in","r",stdin);
freopen("ti.out","w",stdout);
read(n);
for (int i=1;i<=n;++i) read(a[i]);
int now=0;
for (int i=1;i<=n;++i)
{
if (a[i]>now) ans+=6*(a[i]-now)+5;
else ans+=4*(now-a[i])+5;
now=a[i];
}
cout<<ans<<endl;
fclose(stdin);
fclose(stdout);
return 0;
}
2. 水水の數
[問題描述]
一天,無聊的水水在紙上的不同位置寫著一個又一個數字。最終,水水一
共寫了 N 個數字,每個數字書寫位置的座標分別為(xi,yi)。
看著紙上的數字,水水突然腦洞大開。定義一個數字到另一個數字的“水
氏距離”為兩個數字在豎直方向上的差值。水水想在所有的數字中找到一個數
字,這個數字滿足其他所有數字到它的“水氏距離”之和最短。
然而,由於滿足條件的數字可能不止一個。因此,水水只想知道其他所有
數字到這個數字的“水氏距離”之和。
[輸入格式]
輸入包含 N+1 行。
第一行一個整數 N。
之後 N 行, 每行兩整數 xi,yi 表示第 i 個數字被寫在座標(xi,yi)處。
[輸出格式]
輸出包含 1 行。
第一行一個整數,即所求“水氏距離”之和。
[樣例輸入]
5
1 2
2 2
1 3
3 -2
3 3
[樣例輸出]
6
尋找中位數。
對於奇數:a[n/2+1]一定是最終的答案。
對於偶數:a[n/2]~a[n/2+1]的區間範圍一定是最終的答案。
可以根據絕對值的幾何意義進行證明。
#include<bits/stdc++.h>
using namespace std;
#define MAXN 2000000
int a[MAXN];
void read(int &readnum)
{
int s=0,w=1;char c=getchar();
while (c<'0' || c>'9') {if (c=='-') w=-1;c=getchar();}
while (c>='0' && c<='9') s=s*10+c-48,c=getchar();
readnum=s*w;
}
int main()
{
freopen("num.in","r",stdin);
freopen("num.out","w",stdout);
int n;
read(n);
for (int i=1;i<=n;++i)
{
int x,y;
read(x);
read(y);
a[i]=y;
}
sort(a+1,a+n+1);
int ans=0;
for (int i=1;i<=n;++i) ans+=abs(a[i]-a[n/2+1]);
cout<<ans<<endl;
fclose(stdin);
fclose(stdout);
return 0;
}
3. 水水の字
[問題描述]
水水是一名出色的 OIer,在訓練過程中,他發現各大 OJ 並不是很好用,
於是決定自己建立一個 OJ。 可是水水希望在建立 OJ 系統之前瞭解他一共要創
建多少個資料夾。
在即將構建 OJ 的 Linux 系統下可以用路徑來描述資料夾,路徑為一個包
含若干部分的字串,之間用“/”(不含引號)分隔。每部分均為一個資料夾
的名稱,且表示這個資料夾的父資料夾為前一部分描述的資料夾。每個路徑的
第 1 個字元總是“/”,且不會出現兩個連續的“/”,最後一個字元不會是“/”。
而所有資料夾僅包含數字和字母。
例如: /home/fj/summer 表示根目錄下有一個名稱為 home 的資料夾,
這個 home 資料夾下有一個名稱 fj 的資料夾,這個名稱為 fj 的資料夾下有一
個名稱為 summer 的資料夾。此時要構造出這樣的路徑關係,除根目錄外還需
要 3 個資料夾。
現在先給出 N 個路徑,一開始除了根目錄不存在任何資料夾,在每給出一
個路徑後,對於第 i 個路徑,你需要輸出的是若要讓第 1 個路徑到第 i 個路徑
存在,最少需要新建多少個資料夾。
[輸入格式]
輸入包含 N+1 行。
輸入檔案第 1 行為一個正整數 N。
接下來 N 行,每行為一個描述路徑的字串,長度均不超過 100。
[輸出格式]
輸出包含 N 行。
每行 1 個正整數,第 i 行輸出若要使第 1 個路徑到第 i 個路徑存在,最少
需要新建多少個資料夾。
[樣例輸入]
6
/data
/data/build
/data/eat
/data/build
/build/build
/data
[樣例輸出]
1
2
3
3
5
5
STL MAP
對於每一個檔案,當且僅當所有上級節點的檔案都相同才表示重複。
因此我們可以設定Map,把當前檔案以及它的所有上級檔案作為一個字串存入Map中,如果在Map中存在這個數字就說明是重複的,否則就需要新增檔案。
CODE
#include<bits/stdc++.h>
using namespace std;
char s[2000][2000];
map<string,bool>v;
int main()
{
freopen("dir.in","r",stdin);
freopen("dir.out","w",stdout);
int n,ans=0;
cin>>n;
for (int i=1;i<=n;++i) cin>>s[i];
for (int i=1;i<=n;++i)
{
string temp;
int len=strlen(s[i]);
for (int j=0;j<len;++j)
{
temp+=s[i][j];
if (s[i][j+1]=='/' || j==len-1)
if (!v[temp]) ans++,v[temp]=1;
}
cout<<ans<<endl;
}
fclose(stdin);
fclose(stdout);
return 0;
}
4. 水水の圖
[問題描述]
水水將去 K 國旅遊。 K 國有 N 個省份,其中, 1 號省份是首都。
N 個省份之間有 M 趟火車,火車是雙向的。定義第 i 個省份的轉車次數為
從首都到這個省份,最少需要轉幾趟火車。如果從首都無法到達 i 省份,那麼
i 省份的轉車次數是無窮大。
由於洪水等自然原因,有些火車會停運。
當一趟火車停運之後, 2~N 每個省份的轉車次數不變,這種情況水水尚且
可接受,否則,水水則可能取消這次旅行。
現在水水想提前知道,哪些火車的停運是可接受的?以便提早做出旅行決
定。 如果可接受的火車不存在,輸出一行“NO”(不含引號)。
[輸入格式]
輸入包含 M+1 行。
第一行兩個正整數 N, M。
接下來 M 行每行兩個正整數 a, b。 按 1~M 的順序表示第 i 趟火車連線 a
和 b 兩個省份。 保證 a 不等於 b,且同一對 a, b 只會出現一次。
[輸出格式]
若干整數,從小到大排序,表示所有的可接受取消的火車序號。
[樣例輸入]
5 6
1 2
1 3
1 4
3 4
對於每一條可以刪除的邊,必然有下列特點:
1.有多條可以終點的路徑,刪除一條顯然不影響。
2.這一條邊不再最短路圖上,在bfs的時候進行統計即可。
CODE
#include<bits/stdc++.h>
using namespace std;
int n,m;
vector<int>a[300000];
int q[10000000],h,t;
int vis[1000000];
int dis[1000000];
int x[300000],y[300000],in[300000];
inline void read(int &readnum)
{
int s=0;char c=getchar();
while (c<'0' || c>'9') c=getchar();
while (c>='0' && c<='9') s=s*10+c-48,c=getchar();
readnum=s;
}
int main()
{
freopen("train.in","r",stdin);
freopen("train.out","w",stdout);
cin>>n>>m;
for (int i=1;i<=m;++i)
{
read(x[i]),read(y[i]);
a[x[i]].push_back(y[i]);
a[y[i]].push_back(x[i]);
}
memset(in,0,sizeof(in));
memset(vis,0,sizeof(vis));
memset(dis,127,sizeof(dis));
vis[1]=1;dis[1]=0;h=t=1;q[1]=1;
for (;h<=t;++h)
{
int p=q[h];
for (int i=0;i<a[p].size();++i)
{
int np=a[p][i];
if (!vis[np])
{
q[++t]=np;
vis[np]=1;
dis[np]=dis[p]+1;
in[np]=1;
continue;
}
if (dis[p]+1==dis[np]) in[np]++;//統計到達一個點的路徑總數
}
}
bool flag=false;
for (int i=1;i<=m;++i)
{
int c=x[i],d=y[i];
if (dis[c]>dis[d]) swap(c,d);//保證了c的深度小於d的深度
if (dis[d]-dis[c]!=1 || in[d]>1)//第一條件判斷是否在最短路圖上,第二個點判斷是否可以存在多條相同的邊
{
printf("%d\n",i);
flag=1;
}
}
if (!flag) printf("NO\n");
return 0;
fclose(stdin);
fclose(stdout);
return 0;
}