1. 程式人生 > >【考題題解】NOIP模擬賽Day1

【考題題解】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;
}