【题解】【模拟】—— [CSP-J 2021] 小熊的果篮

news2024/12/28 20:34:04

【题解】【模拟】—— [CSP-J 2021] 小熊的果篮

  • [CSP-J 2021] 小熊的果篮
    • 题目描述
    • 输入格式
    • 输出格式
    • 输入输出样例
      • 输入 #1
      • 输出 #1
      • 输入 #2
      • 输出 #2
      • 输入 #3
      • 输出 #3
    • 提示
  • 思路1.数组模拟(70分)
    • 1.1.题意解析
    • 1.2.参考代码
  • 思路2.双向链表模拟(60分)
    • 2.1.题意解析
    • 2.2.参考代码
  • 解法1.双向链表模拟优化
    • 3.1.题意解析
    • 3.2.AC代码
  • 解法2.并查集
    • 4.1.题意解析
    • 4.2.AC代码
  • 5.结尾语

前置知识:双向链表,并查集

[CSP-J 2021] 小熊的果篮

戳我查看题目(洛谷)

题目描述

小熊的水果店里摆放着一排 n n n 个水果。每个水果只可能是苹果或桔子,从左到右依次用正整数 1 , 2 , … , n 1, 2, \ldots, n 1,2,,n 编号。连续排在一起的同一种水果称为一个“块”。小熊要把这一排水果挑到若干个果篮里,具体方法是:每次都把每一个“块”中最左边的水果同时挑出,组成一个果篮。重复这一操作,直至水果用完。注意,每次挑完一个果篮后,“块”可能会发生变化。比如两个苹果“块”之间的唯一桔子被挑走后,两个苹果“块”就变成了一个“块”。请帮小熊计算每个果篮里包含的水果。

输入格式

第一行,包含一个正整数 n n n,表示水果的数量。

第二行,包含 n n n 个空格分隔的整数,其中第 i i i 个数表示编号为 i i i 的水果的种类, 1 1 1 代表苹果, 0 0 0 代表桔子。

输出格式

输出若干行。

i i i 行表示第 i i i 次挑出的水果组成的果篮。从小到大排序输出该果篮中所有水果的编号,每两个编号之间用一个空格分隔。

输入输出样例

输入 #1

12
1 1 0 0 1 1 1 0 1 1 0 0

输出 #1

1 3 5 8 9 11
2 4 6 12
7
10

输入 #2

20
1 1 1 1 0 0 0 1 1 1 0 0 1 0 1 1 0 0 0 0

输出 #2

1 5 8 11 13 14 15 17
2 6 9 12 16 18
3 7 10 19
4 20

输入 #3

见附件中的 fruit/fruit3.in。

输出 #3

见附件中的 fruit/fruit3.ans。

提示

【样例解释 #1】

这是第一组数据的样例说明。

所有水果一开始的情况是 [ 1 , 1 , 0 , 0 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 0 ] [1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0] [1,1,0,0,1,1,1,0,1,1,0,0],一共有 6 6 6 个块。

在第一次挑水果组成果篮的过程中,编号为 1 , 3 , 5 , 8 , 9 , 11 1, 3, 5, 8, 9, 11 1,3,5,8,9,11 的水果被挑了出来。

之后剩下的水果是 [ 1 , 0 , 1 , 1 , 1 , 0 ] [1, 0, 1, 1, 1, 0] [1,0,1,1,1,0],一共 4 4 4 个块。

在第二次挑水果组成果篮的过程中,编号为 2 , 4 , 6 , 12 2, 4, 6, 12 2,4,6,12 的水果被挑了出来。

之后剩下的水果是 [ 1 , 1 ] [1, 1] [1,1],只有 1 1 1 个块。

在第三次挑水果组成果篮的过程中,编号为 7 7 7 的水果被挑了出来。

最后剩下的水果是 [ 1 ] [1] [1],只有 1 1 1 个块。

在第四次挑水果组成果篮的过程中,编号为 10 10 10 的水果被挑了出来。

【数据范围】

对于 10 % 10 \% 10% 的数据, n ≤ 5 n \le 5 n5
对于 30 % 30 \% 30% 的数据, n ≤ 1000 n \le 1000 n1000
对于 70 % 70 \% 70% 的数据, n ≤ 50000 n \le 50000 n50000
对于 100 % 100 \% 100% 的数据, 1 ≤ n ≤ 2 × 10 5 1 \le n \le 2 \times {10}^5 1n2×105

【提示】

由于数据规模较大,建议 C/C++ 选手使用 scanfprintf 语句输入、输出。

思路1.数组模拟(70分)

1.1.题意解析

    这道题看上去非常简单,直接使用数组模拟就行了。可是它难就难在单纯使用数组来维护会达到 O ( N 2 ) O(N^2) O(N2)的时间复杂度,铁定超时。如下:
在这里插入图片描述
    虽然不是正解,但我还是贴出来,给大家提供一种思路。

1.2.参考代码

#include<bits/stdc++.h>
using namespace std;
int main()
{
	//用数组a存储水果的种类,flag[i]存储i号水果是否被取出
    int n,a[200010]={},flag[200010]={},cnt=0,prev,is_take=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    while(cnt<n)//用cnt统计被取出的水果的个数 
    {
    	is_take=0;//用is_take存储第一个块头是否被取出 
    	for(int i=1;i<=n;i++)
    	{
    		if(flag[i])continue;//如果这个水果已经被取出了,跳出 
    		if(!is_take)//如果是第一个没有被取出的水果 
    		{
    			is_take=1;//初始化状态 
    			prev=!a[i];
			}
    		if(a[i]!=prev)//如果是新的一块,取出块头 
    		{
    			flag[i]=1;
    			prev=a[i];
    			cnt++;
    			printf("%d ",i);
			}
		}
		printf("\n");//输出换行 
	}
	return 0;
}

思路2.双向链表模拟(60分)

2.1.题意解析

    既然使用数组模拟会超时,那我们可不可以换一种数据结构呢?对了!我们可以使用双向链表来模拟。

    一个基础的双向链表如下:
在这里插入图片描述

    首先定义一个结构体node,用来储存每个节点的信息,如下:

struct node//储存每一个节点的信息 
{
	int kind,prev,next;
	node(int _kind=0,int _prev=0,int _next=0):
	kind(_kind),prev(_prev),next(_next){}
}l[MAXN];

    同时定义一个数组l,用来模拟双向链表。这里有一个小技巧:令l[0]永远为表头。

    然后定义一个变量cnt,用来记录双向链表l的长度和最后一个位置。

    接下来,我们需要分装两个基础的函数:插入和删除,具体操作如下:

void insert_back(int x,int kind)//插入节点的函数 
{
	int now=x;
	l[++cnt]=node(kind,now,l[x].next);//增加编号为cnt新节点 
	if(l[x].next)l[l[x].next].prev=cnt;//x后面有节点,前驱元素改为此节点
	l[x].next=cnt;//x的后驱节点改为此节点 
}
void del(int x)//删除节点的函数 
{
	int prv=l[x].prev,nxt=l[x].next;//取出x的前驱元素和后驱元素
	if(nxt)l[nxt].prev=prv;//x后面有节点,和x的前驱元素连接
	l[prv].next=nxt;//x的前驱元素和后驱元素连接
	cnt--;//长度减一 
}

    然后就是遍历整个双向链表。使用一个变量now记录当前枚举到的节点。如果当前节点是一个块的开头(即和上一个节点的品种不一样),那么就取出。否则就now=l[now].next注意:要先取出第一个节点。

    但这其实根遍历数组没有太大的本质区别,甚至比用数组模拟的分还要低 ,时间复杂度还是 O ( n 2 ) O(n^2) O(n2)。如下:
在这里插入图片描述

2.2.参考代码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 200010
struct node//储存每一个节点的信息 
{
	int kind,prev,next;
	node(int _kind=0,int _prev=0,int _next=0):
	kind(_kind),prev(_prev),next(_next){}
}l[MAXN];
int cnt,n;
void insert_back(int x,int kind)//插入节点的函数 
{
	int now=x;
	l[++cnt]=node(kind,now,l[x].next);//增加编号为cnt新节点 
	if(l[x].next)l[l[x].next].prev=cnt;//x后面有节点,前驱元素改为此节点
	l[x].next=cnt;//x的后驱节点改为此节点 
}
void del(int x)//删除节点的函数 
{
	int prv=l[x].prev,nxt=l[x].next;//取出x的前驱元素和后驱元素
	if(nxt)l[nxt].prev=prv;//x后面有节点,和x的前驱元素连接
	l[prv].next=nxt;//x的前驱元素和后驱元素连接
	cnt--;//长度减一 
}
int main()
{
    scanf("%d",&n);
    for(int i=1,prev=0;i<=n;i++)//初始化 
    {
    	int kind;
    	scanf("%d",&kind);
    	insert_back(prev,kind);
    	prev=i;
	}
	while(cnt)
	{
		printf("%d ",l[0].next);
		if(cnt==1)break;
		int now=l[l[0].next].next,prev=l[l[0].next].kind;
		del(l[0].next);//第一个元素总要取出
		while(now)//遍历链表
		{
			if(l[now].kind!=prev)//块头,取出 
			{
				prev=!prev;
				int nxt=l[now].next;
				printf("%d ",now); 
				del(now);
				now=nxt;
			}
			else now=l[now].next;
		}
	    puts("");
	}
	return 0;
}

解法1.双向链表模拟优化

3.1.题意解析

    既然以上的双向链表还是遍历每个节点,呢我可不可以优化一下,使得双向链表只遍历每个块呢?

    当然可以,定义一个可变数组head,用来存储每个块的块头。并在输入时预处理。在遍历时直接把块头节点输出并删除。

    但是现在就有了一个难点:怎么样判定下一个节点会不会成为一个块的新块头呢?

    如果一个块头被取出,它后面的点成了块头,那么它一定具有以下两个特征。

1.l[t].kind==l[l[t].next].kind。此节点和此节点的下一个种类一样,即是当前块的新块头;
2.l[t].kind!=l[l[t].prev].kind,此节点和上一个节点种类不一样,即不会被上一个块合并。

注意:
    1.新块头要先用临时数组tmp存储,以免对当前遍历造成影响。
    2.如果head数组空了,跳出循环。

3.2.AC代码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 200010
struct node//储存每一个节点的信息
{
	int kind,prev,next;
	node(int _kind=-1,int _prev=0,int _next=0):
	kind(_kind),prev(_prev),next(_next){}//结构体初始化函数
}l[MAXN];//双向链表
int cnt,n;
void insert_back(int x,int kind)//在节点x后面插入值为kind的节点的函数
{
	l[++cnt]=node(kind,x,l[x].next);//增加编号为cnt新节点
	if(l[x].next)l[l[x].next].prev=cnt;//x后面有节点,前驱元素改为此节点 
	l[x].next=cnt;//x的后驱节点改为此节点
}
void del(int x)//删除节点x的函数 
{
	int prv=l[x].prev,nxt=l[x].next;//取出x的前驱元素和后驱元素
	if(nxt)l[nxt].prev=prv;//x后面有节点,和x的前驱元素连接
	l[prv].next=nxt;//x的前驱元素和后驱元素连接
}
int main()
{
    scanf("%d",&n);
    int prev;//记录上一个节点的种类
    vector<int>head(1,1);//初始化,第一个节点绝对是块头 
    for(int i=1;i<=n;i++)
    {
    	int kind;
    	scanf("%d",&kind);
    	insert_back(i-1,kind);//插入链表
    	if(i==1)prev=kind;//初始化
    	else if(kind!=prev)//如果是新的块
		{
			head.push_back(i);//新增一个块头
			prev=!prev;//状态取反
		}
	}
	while(!head.empty())//只要还有待取出的块头就继续循环
	{
		vector<int>tmp;//暂时储存下一轮的块头
        for(int i=0;i<head.size();i++)//循环取出
        {
        	int t=head[i];//先取出当前块头
        	printf("%d ",t);//输出
        	del(t);//删除节点t
        	/*如果此节点和此节点的下一个种类一样(即是当前块的新块头),
			  且此节点和上一个节点种类不一样(即不会被上一个块合并),
			  那么就是新块头*/
        	if(l[t].kind==l[l[t].next].kind&&l[t].kind!=l[l[t].prev].kind)
                tmp.push_back(l[t].next);
		}
		head=tmp;//赋值
		puts("");
	}
	return 0;
}

解法2.并查集

4.1.题意解析

    这道题还可以使用并查集来做,如果不会的同学可以自行上网搜索。或者看看这一篇。目前只需要了解其原理就行了,代码实现在底下有。

    在删除一个数之后,我们将 这个数 这个数 这个数 这个数 − 1 这个数-1 这个数1相连。就形成了一些。在删除块头的时候,这个块头所在的树的祖先节点,也就是根节点,就是下一个没有被删除的块头。如果不理解的话可以自己画一下图带入一下数据。

    定义一个数组head,储存每个块的块头。定义一个数组size,储存每个块的大小。定义一个数组fafa[i]代表i所属的数的代表(根节点)。最后定义一个变量sum_void,储存当前连续被取空的块的个数(原因请看下面)。

    现在还有一个问题,什么情况下需要新建一个块呢?

1.这一个块不会在这一轮被取光(不然就没有意义了);
2.这是第一个块,或者说当前新块的个数为0;
3.前一个块不会在这一轮被取空(不会导致和上一个块合并);
4.前面被取空的块的个数为偶数(和上一个同理)。

    最后附上并查集的模版

int find(int x)//寻找x家族的代表,顺便进行路径压缩 
{
	if(fa[x]==x)return x;//代表就是本人,返回 
	return fa[x]=find(fa[x]);//路径压缩 
}
void join(int c1,int c2)//合并两个集合 
{
	int f1=find(c1),f2=find(c2);//找到两个元素的代表 
	if(f1<f2)swap(f1,f2);//如果f1更小就交换 
	fa[f2]=f1;//修改代表 
}

注:此思路是我借鉴的洛谷上一位大佬的思路发现的,请见谅。

4.2.AC代码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 200010
int n,a[MAXN],size[MAXN],head[MAXN],fa[MAXN],sum,cnt=1,sum_void;
/*用size储存每个块的大小,head储存要取出来的的一个水果,fa储存每个块的代表
  cnt储存块的个数,sum_void储存上一个连续的取完的块的个数*/
int size2[MAXN],head2[MAXN],cnt2;//临时存储
int find(int x)//寻找x家族的代表,顺便进行路径压缩 
{
	if(fa[x]==x)return x;//代表就是本人,返回 
	return fa[x]=find(fa[x]);//路径压缩 
}
void join(int c1,int c2)//合并两个集合 
{
	int f1=find(c1),f2=find(c2);//找到两个元素的代表 
	if(f1<f2)swap(f1,f2);//如果f1更小就交换 
	fa[f2]=f1;//修改代表 
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)//读入并预处理
		scanf("%d",&a[i]),fa[i]=i;
	size[1]=1,head[1]=1;//将1号水果放进果篮里
	for(int i=2;i<=n;i++)//将2到n号水果放进果篮里 
	{
		if(a[i]!=a[i-1])head[++cnt]=i;
		//此元素与上一个元素不一样,新增一个块 
		size[cnt]++;//此块的大小加一 
	}
	while(sum<n)//循环直到取出n个元素 
	{
		for(int i=1;i<=cnt;i++)//将每一个块头和它前一个元素连接,方便查找 
		    printf("%d ",head[i]),join(head[i]-1,head[i]);
		printf("\n");
		sum+=cnt;//取出cnt块 
		cnt2=sum_void=0;//赋初值 
		for(int i=1;i<=cnt;i++)//处理每个块 
		{
			if(size[i]>1)//如果这个块不会在这一轮被取光 
			{
				//第一个块或者前一个块有元素或者前面连续的被取空的块有偶数个 
				if(cnt2==0||size[i-1]>1||sum_void%2==0)
				    head2[++cnt2]=find(head[i])+1,size2[cnt2]=0;//新建一个块 
				size2[cnt2]+=size[i]-1;//这个块的大小是上一个块减一 
				sum_void=0;//连续的空的块的个数清零 
			}
			else sum_void++;//否则就是空的块 
		}
		cnt=cnt2;//更新块的个数 
		for(int i=1;i<=cnt;i++)//更新每一个块的大小和块头 
		    size[i]=size2[i],head[i]=head2[i];
	}
	return 0;
}

5.结尾语

    其实这道题还可以用许多数据结构维护,比如vectorqueueset,线段树等。是一道很好的练习数据结构的题。但由于篇幅关系就只给大家讲这么多了。感兴趣的话可以自行上网查询。

喜欢就订阅此专辑吧!

【蓝胖子编程教育简介】
蓝胖子编程教育,是一家面向青少年的编程教育平台。平台为全国青少年提供最专业的编程教育服务,包括提供最新最详细的编程相关资讯、最专业的竞赛指导、最合理的课程规划等。本平台利用趣味性和互动性强的教学方式,旨在激发孩子们对编程的兴趣,培养他们的逻辑思维能力和创造力,让孩子们在轻松愉快的氛围中掌握编程知识,为未来科技人才的培养奠定坚实基础。

欢迎扫码关注蓝胖子编程教育
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2076525.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FastCGI简述

FastCGI (FCGI) 是一种协议&#xff0c;用于改善 Web 服务器和应用程序之间的通信效率。它是在 CGI&#xff08;Common Gateway Interface&#xff09;的基础上发展起来的&#xff0c;旨在解决 CGI 在处理大量并发请求时存在的性能问题。 CGI的由来 最早的Web服务器只能简单地…

Java入门:06.Java中的方法--扩展(值传递和址传递与主方法传参)

1 值传递和址传递 值传递 方法调用时&#xff0c;如果传递的实际参数是一个基本类型的数据&#xff0c;那么如果只有形式参数发生改变的话&#xff0c;实参是不会发生变化的&#xff0c;因为我们传递的是变量中具体的数据。 main(){int i 10 ;t1(i) ; //值传递System.out.p…

Nacos源码分析

Nacos源码分析 1.下载Nacos源码并运行 要研究Nacos源码自然不能用打包好的Nacos服务端jar包来运行&#xff0c;需要下载源码自己编译来运行。 1.1.下载Nacos源码 Nacos的GitHub地址&#xff1a;https://github.com/alibaba/nacos 如果需要研究其他版本的&#xff0c;也可以…

自动化代码报错:ElementClickInterceptedException 解决方案

在自动化测试中&#xff0c;如果有多个弹窗出现&#xff0c;代码执行可能会遇到ElementClickInterceptedException的错误&#xff0c;表明元素点击被拦截&#xff1a; 一般由于以下原因&#xff1a; 一、页面加载未完成 在页面尚未完全加载完成时尝试点击某个元素&#xff0c…

Vue3基础1

1、optionsApi 与 Composition Api 选项式与组合式 组合就是一个一个 的函数 &#xff0c;每个函数里都有 data&#xff0c;methods&#xff0c;compute 等等 2、拉开序幕的setup setup执行时机 在 beforeCreate之前 <template><div class"person">&l…

Qt:玩转QPainter序列四补充(裁剪家族)

前言 本文补充上篇缺失的裁剪家族。 正文 9.裁剪家族 QRegion clipRegion() const; 功能&#xff1a;返回当前的剪裁区域 (clip region)。剪裁区域限制了绘制操作的范围&#xff0c;只有在剪裁区域内的部分才会被绘制。返回值&#xff1a;一个 QRegion 对象&#xff0c;表…

【c语法】##__VA_ARGS__与__VA_ARGS__

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 文章目录 引言__VA_ARGS__ 引言 在调试过程中&#xff0c;我们经常会自定义打印&#xff0c;比如日志信息的输出&#xff0c;这时就会用VA_ARGS,接下来详细讲解&#xff01; VA_ARGS __VA_ARGS__是C语言设定…

数据展现新方式,Excel子弹图制作全攻略!

在做数据汇报时&#xff0c;如何让你的报告脱颖而出&#xff0c;瞬间吸引老板和同事的注意力&#xff1f;答案就是子弹图&#xff01;今天&#xff0c;我们就来教你如何利用Excel这个强大的工具&#xff0c;轻松制作出专业又美观的子弹图&#xff0c;不论你是数据小白还是职场老…

sqli-labs靶场通关攻略(31-35关)

第31关&#xff08; ") 闭合&#xff09; 查数据库 ?id") union select 1,2,database() -- 查表 ?id") union select 1,2,group_concat(table_name) from information_schema.tables where table_schemasecurity-- 查列 ?id") union select 1,2,gro…

量化交易backtrader实践(四)_评价统计篇(2)_评价输出

上节回顾 上一节我们对backtrader内置的一堆评价指标进行了实践&#xff0c;从视觉上对这些评价指标的输出参数有了个大概的了解。接下来&#xff0c;我们在循环对多支股票或多个策略进行回测的时候&#xff0c;就可以将评价的一些值进行输出了&#xff0c;这样就能对于股票和…

建筑企业如何搭建数据仓库?做好这三步,大幅节约企业成本!

在当今这个数据驱动的时代&#xff0c;建筑企业正面临着前所未有的挑战和机遇。随着项目规模的扩大和市场环境的复杂化&#xff0c;如何有效管理和分析海量数据&#xff0c;已经成为提升企业竞争力的关键。数据仓库作为企业数据管理的核心&#xff0c;不仅能够整合分散的数据资…

攻防世界 reverse_re3

前言&#xff1a;做题笔记。 下载解压 查壳。 64ida 打开 查找字符并跟进 wasd一看&#xff0c;这题就是关于迷宫的题。跟进看看。 懵。。。不过还是得仔细看看。 观察发现。 进去看看。 然后最开始&#xff0c;因为数据太多把我卡住了。。。 回过头仔细看看。 猜测dword_202…

企业建站技术路线探索

前言 企业站是指企业或公司创建的官方网站&#xff0c;用于展示企业信息、产品和服务。它通常包括公司简介、产品或服务介绍、联系方式、新闻更新等内容。企业站的目的是提升品牌形象、提供客户服务和促进业务发展。在跨境贸易中&#xff0c;企业建站尤为关键&#xff0c;因为…

数据库集群技术

源码安装mysql mysql.com [https://downloads.mysql.com/archives/community/]: 官网下载 安装依赖性&#xff1a; [rootmysql-node2 ~]# dnf install cmake gcc-c openssl-devel \ ncurses-devel.x86_64 libtirpc-devel-1.3.3-8.el9_4.x86_64.rpm rpcgen.x86_64 下载并解压源…

Netty系列-1 NioEventLoopGroup和NioEventLoop介绍

背景 从本文开始开启一个新的专题Netty系列&#xff0c;用于收集Netty相关的文章&#xff0c;内容包含Netty的使用方式、运行原理等。 基于io.netty:netty-all:4.1.49.Final版本进行介绍 1.NioEventLoopGroup 介绍NioEventLoopGroup之前&#xff0c;有几个相关的组件需要提前…

idea导入maven项目(别人的项目)爆红

作为一个经常学习交流的人&#xff0c;或者工作需要&#xff0c;我们都或多或少会把别人写好的代码拷贝过来学习或编辑&#xff0c;大多数时候都是把整个项目拿过来;但是往往把代码拿到之后放在自己电脑用 idea 打开的时候就会出现 pom.xml 文件红线报错&#xff0c;然后倒入的…

大模型企业应用落地系列》基于大模型的对话式推荐系统》技术架构设计全攻略

注&#xff1a;此文章内容均节选自充电了么创始人&#xff0c;CEO兼CTO陈敬雷老师的新书《自然语言处理原理与实战》&#xff08;人工智能科学与技术丛书&#xff09;【陈敬雷编著】【清华大学出版社】 文章目录 大模型企业应用落地系列全貌基于大模型的对话式推荐系统》技术架…

如何使用ssm实现投稿系统+vue

TOC ssm231论文投稿系统vue 系统概述 1.1 研究背景 如今互联网高速发展&#xff0c;网络遍布全球&#xff0c;通过互联网发布的消息能快而方便的传播到世界每个角落&#xff0c;并且互联网上能传播的信息也很广&#xff0c;比如文字、图片、声音、视频等。从而&#xff0c;…

软件测试 | 概念(1)

目录 前言 需求的概念 开发模型 软件的生命周期 常见开发模型 瀑布模型 螺旋模型 增量模型&#xff0c;迭代模型 敏捷模型 Scrum模型 测试模型 V模型 W模型&#xff08;双V模型&#xff09; 前言 测试&#xff1a;验证软件的特性是否满足用户的需求。 用户的需求…

vue3前端界面布置到服务器,使用户能用网址访问到界面

1.下载Nginx&#xff1a; nginx: download 2.下载好的Nginx解压缩&#xff0c; 在解压缩的文件夹下找到conf > nginx.conf&#xff0c;修改nginx.conf中的server&#xff0c;配置服务器的ip地址和端口号 3.执行npm run build命令&#xff0c;vue生成的dist下的文件全部放置在…