第十次CCF-CSP(Markdown、地铁修建)

第十次CCF-CSP

第三题 Markdowm

原题链接:3244. Markdown - AcWing题库

思路分析:

这道大模拟题,对于我而言主要有下面几个难点:

  • 输入数据不知道怎么处理

    vector<string> str;
    while(getline(cin,s))	//只有遇到结束符 Ctrl z 或者 EOF才结束
        str.push_back(s)
    
  • 怎么找到每一个区块?

    for(int i = 0;i<str.size();i++)
    {
        if(str[i].empty())	//这里是把空行跳过
            continue;	
        int j = i + 1;	//j 用来“测量” 这个区块有多少行
        while(j<str.size() && !str[j].empty())
            j++;
        solve(i,j-1);	//i到j-1 就是区块的行数 
        i=j-1;
    }
    

处理完这两个问题之后,下面正式进入题目的分析:

对于每一个区块,有三种可能:

  • 段落
  • 标题
  • 无序列表

而对于每一个区块,其中的每一行都可能会有

  • 强调

  • 超级链接

  • 强调中 嵌套超级链接

  • 超级链接中 嵌套强调

所以我们可以写两个函数,一个处理区块,一个处理区块中的每一行。

代码展示

#include<bits/stdc++.h>

using namespace  std;

vector<string> str;

void solve_line(string s)	//处理每行的具体细节
{
	int i;
	for (i = 0; i < s.size(); i++)
	{
		if (s[i] != ' ')
			break;
	}

	for (i; i < s.size(); i++)
	{
		if (s[i] == '_')	//处理强调
		{
			cout << "<em>";
			for (i++; s[i] != '_'; i++)
			{
				if (s[i] == '[')	//强调中嵌套超链接
				{
					string text, link;
					for (i++; s[i] != ']'; i++)	//text
					{
						text += s[i];
					}
					for (i++; s[i] != ')'; i++)
					{
						if (s[i] == '(')
							continue;
						link += s[i];
					}
					cout << "<a href=\"" << link << "\">" << text << "</a>";
				}
				else
				{
					cout << s[i];
				}
			}
			cout << "</em>";
		}
		else if (s[i] == '[')	//处理超链接
		{
			cout << "<a href=\"";

			string text, link;
			for (i++; s[i] != ']'; i++) //text
			{
				if (s[i] == '_')	//超链接中嵌套强调
				{
					text += "<em>";
					for (i++; s[i] != '_'; i++)
					{
						text += s[i];
					}
					text += "</em>";
				}
				else
				{
					text += s[i];
				}
			}
			for (i++; s[i] != ')'; i++) //link
			{
				if (s[i] == '(')
					continue;
				//link += "<a href=";
				if (s[i] == '_')
				{
					link += "<em>";
					for (i++; s[i] != '_'; i++)
					{
						link += s[i];
					}
					link += "</em>";
				}
				else
				{
					link += s[i];
				}
			}
			cout << link << "\"" << ">" << text << "</a>";
		}
		else //其他的 普通字符 直接输出
			cout << s[i];
	}
	//cout << '\n';
}
void solve(int a, int b)	//a,b表示区块开始的行号 结束的行号
{
	if (str[a][0] == '#')
	{
		string s;
		int k = 0;
		for (int i = 0; i < str[a].size(); i++)
		{
			if (str[a][i] == '#')
				k++;
		}
		cout << "<h" << k << ">";
		solve_line(str[a].substr(k));
		cout <<  "</h" << k << ">" << endl;
	}
	else if (str[a][0] == '*')
	{
		cout << "<ul>\n";
		for (int i = a; i <= b; i++)	//每一行
		{
			cout << "<li>";
			solve_line(str[i].substr(1));
			cout << "</li>\n";
		}
		cout << "</ul>\n";

	}
	else
	{
		cout << "<p>";
		for (int i = a; i <= b; i++)
		{
			solve_line(str[i]);
			if(i!=b)
				cout << '\n';
		}
		cout << "</p>\n";
	}
	
}

int main()
{
	string s;
	while (getline(cin, s))
	{
		str.push_back(s);
	}
	for (int i = 0; i < str.size(); i++)
	{
		if (str[i].empty())
			continue;
		int j = i + 1;
		while (j < str.size() && !str[j].empty())	//找到区块
			j++;
		solve(i, j - 1);	//处理区块
		i = j - 1;
	}
	return 0;
}

踩坑

  • 注意超链接要先存起来,再输出,不能一边遍历一边输出
  • 注意每一行 换行时 </p> 要放在最后一行的末尾

第四题:地铁修建

原题链接:3245. 地铁修建 - AcWing题库

思路分析

题目描述有点复杂,把题目翻译一下就是:

给定一个无向图,有n个节点,m条边。要求最多选取n条边的前提下,使得节点1和节点n连通求所用边最大的权重的最小值

(最大的最小—可以联想到二分)

那么要怎么二分?

对于题意:假设修建地铁最少需要 mid 天,若在所有施工公司中修建天数小于 mid 天的公司中选取 1–n 个公司,可以使得节点1和节点n连通。那么此时的mid还可以再尝试变小。

翻译一下就是:

若从边权小于等于 mid 的边中选择边,找到节点1到节点n的最短路(每条路的长度是1),使得最短路的长度小于等于n。则此时的mid符合题意。

所以本题本质上是考察二分和BFS(最短路问题)。

难点

  • 用数组模拟链表
//定义:
const int N = 1e6+10,M=4e6+10;
//h[i] 是以i为起点的链表的头指针, e[] 存放边的节点,w[] 存放边的权重, ne[] 存放下一个节点的索引(类似于指针
int h[N],e[M],w[M],ne[M],idx;


//初始化:
memset(h,-1,sizeof h);

//赋值:
void add(int a,int b,int c)
{
	e[idx]=b;	//是将节点b放在idx边上
    w[idx]=c;	//边idx 的权重
    ne[idx]=h[a];//记住此时的头结点的索引
    h[a]=idx++;	//头指针移动(头插法)
}

//遍历:
for(int i = h[t];i!=-1;i=ne[i])
{
	int j = e[i];
    ...
}

代码展示

#include<bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5, M = 4e6 + 5;
int n, m;
int h[N], e[M], w[M], ne[M], idx;   //注意这里的 N 和 M(简单起见也可以都用较大的M)
queue<int> q;
int dist[N];    //dist[i] 表示 1 到 i 的最短距离

void add(int a, int b, int c)	//赋值
{
	e[idx] = b;
	w[idx] = c;
	ne[idx] = h[a];
	h[a] = idx++;
}

bool check(int mid)
{
	memset(dist, 0x3f, sizeof dist); //路径初始化为最大值
	dist[1] = 0;    

	q.push(1);  //利用bfs
	while (!q.empty())
	{
		int t = q.front();
		q.pop();
		for (int i = h[t]; i!=-1; i = ne[i])	//遍历
		{	
			if (w[i] > mid)	//由题目分析可知 只用权重小于mid 的
				continue;
			int j = e[i];
			if (dist[j] > dist[t] + 1)  //求最短路
			{
				dist[j] = dist[t] + 1;
				q.push(j);
			}
		}
	}
	if (dist[n] <= n)
		return true;
	else
		return false;
}
int main()
{
	cin >> n >> m;
	memset(h, -1, sizeof h);    //初始化
	while (m--)
	{
		int a, b, c;
		cin >> a >> b >> c;
		add(a, b, c);   //无向边
		add(b, a, c);
	}
	int l = 0, r = 1e6; 
	while (l < r)
	{
		int mid = l + r >> 1;
		if (check(mid))
			r = mid;
		else
			l = mid + 1;
	}
	cout << r;
	return 0;
}

相关推荐

  1. CCF-CSP(Markdown、地铁修建

    2024-03-15 08:34:05       42 阅读
  2. 三题:天干地支

    2024-03-15 08:34:05       33 阅读
  3. 一篇,一matlab与spdlog的合作

    2024-03-15 08:34:05       50 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-15 08:34:05       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-15 08:34:05       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-15 08:34:05       82 阅读
  4. Python语言-面向对象

    2024-03-15 08:34:05       91 阅读

热门阅读

  1. 项目示例 - 4.配置中心 - 1.Nacos

    2024-03-15 08:34:05       39 阅读
  2. WPF 两个程序之间传递参数(shell32.dll)

    2024-03-15 08:34:05       48 阅读
  3. 【C语言】宏定义的详解与实践

    2024-03-15 08:34:05       46 阅读
  4. Docker学习笔记

    2024-03-15 08:34:05       41 阅读
  5. 【Linux】文本替换Ubuntu 中 sed 指令的使用指南

    2024-03-15 08:34:05       40 阅读
  6. Uni-app开发Canvas当子组件示例,点点绘制图形

    2024-03-15 08:34:05       44 阅读
  7. Error: ENOENT: no such file or directory, uv_cwd

    2024-03-15 08:34:05       31 阅读
  8. 微信小程序uniapp onshow函数介绍

    2024-03-15 08:34:05       38 阅读
  9. YOLOv8 服务器与本地tensorboard映射

    2024-03-15 08:34:05       44 阅读
  10. SpringBoot自动配置工作流程中变更自动配置

    2024-03-15 08:34:05       38 阅读
  11. fpga相关知识

    2024-03-15 08:34:05       44 阅读