【考题题解】NOIP模拟赛Day1

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Ronaldo7_ZYB/article/details/83626922

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;
}

猜你喜欢

转载自blog.csdn.net/Ronaldo7_ZYB/article/details/83626922
今日推荐