带刷,带刷,刷起来!!!

A:::::::::::::::::::通电(最小生成树,Prim,Kruskal)

题目描述

2015 年,全中国实现了户户通电。作为一名电力建设者,小明正在帮助一带一路上的国家通电。

这一次,小明要帮助 n 个村庄通电,其中 1 号村庄正好可以建立一个发电站,所发的电足够所有村庄使用。

现在,这 n 个村庄之间都没有电线相连,小明主要要做的是架设电线连接这些村庄,使得所有村庄都直接或间接的与发电站相通。

小明测量了所有村庄的位置(坐标)和高度,如果要连接两个村庄,小明需要花费两个村庄之间的坐标距离加上高度差的平方,形式化描述为坐标为(x1​,y1​) 高度为 h1​ 的村庄与坐标为 (x2​,y2​) 高度为h2​ 的村庄之间连接的费用为

高度的计算方式与横纵坐标的计算方式不同。

由于经费有限,请帮助小明计算他至少要花费多少费用才能使这 n 个村庄都通电。

输入描述

输入的第一行包含一个整数 n ,表示村庄的数量。

接下来 n 行,每个三个整数 x,y,h,分别表示一个村庄的横、纵坐标和高度,其中第一个村庄可以建立发电站。

其中,1≤n≤1000,0≤x,y,h≤10000。

输出描述

输出一行,包含一个实数,四舍五入保留 2 位小数,表示答案。

输入输出样例

示例

输入

4
1 1 3
9 9 7
8 8 6
4 5 4

输出

17.41

#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
int n;
struct node{
	int x,y,h;
};
struct node1{
	int qi,zhong;
	double juli;
	node1(int qiqi,int zhongzhong,double julijuli){
		qi=qiqi;
		zhong=zhongzhong;
		juli=julijuli;
	}
};
int fa[10005];
int find(int x){
	if(fa[x]==x) return x;
	return fa[x]=find(fa[x]);
}
bool panduan(int x,int y){
	int tx=find(x);
	int ty=find(y);
	if(tx==ty) return false;
	fa[tx]=ty;
	return true;
}
node dian[1005];
vector<node1> f;
bool cmp(node1 x,node1 y){
	return x.juli<y.juli;
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		int x,y,h;
		cin>>x>>y>>h;
		dian[i].x=x;
		dian[i].y=y;
		dian[i].h=h; 
	}
	
	
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			double s= sqrt((dian[i].x-dian[j].x)*(dian[i].x-dian[j].x)+(dian[i].y-dian[j].y)*(dian[i].y-dian[j].y))+(dian[i].h-dian[j].h)*(dian[i].h-dian[j].h);
			f.push_back(node1(i,j,s));
		}
	}
	sort(f.begin(),f.end(),cmp);
	for(int i=1;i<=n;i++){
		fa[i]=i;
	}
	double ans=0;
	int len=f.size();
	for(int i=0;i<len;i++){
		if(panduan(f[i].qi,f[i].zhong)){
			ans+=f[i].juli;

		}
		
	}
	printf("%0.2f",ans);
	return 0;
} 

B:::::::::::::::::::正约数(唯一分解定理)

题目描述

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

定义阶乘  n!=1×2×3×⋅⋅⋅×n。

请问 100! (100 的阶乘)有多少个正约数。

#include <iostream>
using namespace std;
int a[100];
long long ans=1;
int main(){

    for(int i=2;i<=100;i++){
        int n=i;
        for(int j=2;j<=n;j++){
            while(n%j==0 && n!=0){
                a[j]++;
                n=n/j;
            }
            
        }
    }
    for(int i=1;i<=100;i++){
        ans=(a[i]+1)*ans;
    }
    cout<<ans;
    return 0;
}

 C:::::::::::::::::::迷宫(BFS)

题目描述

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

下图给出了一个迷宫的平面图,其中标记为 1 的为障碍,标记为 0 的为可以通行的地方。

010000
000100
001001
110000

迷宫的入口为左上角,出口为右下角,在迷宫中,只能从一个位置走到这 个它的上、下、左、右四个方向之一。

对于上面的迷宫,从入口开始,可以按 DRRURRDDDR 的顺序通过迷宫, 一共 10 步。其中 D、U、L、R 分别表示向下、向上、向左、向右走。 对于下面这个更复杂的迷宫(30 行 50 列),请找出一种通过迷宫的方式,其使用的步数最少,在步数最少的前提下,请找出字典序最小的一个作为答案。

请注意在字典序中D<L<R<U。

01010101001011001001010110010110100100001000101010
00001000100000101010010000100000001001100110100101
01111011010010001000001101001011100011000000010000
01000000001010100011010000101000001010101011001011
00011111000000101000010010100010100000101100000000
11001000110101000010101100011010011010101011110111
00011011010101001001001010000001000101001110000000
10100000101000100110101010111110011000010000111010
00111000001010100001100010000001000101001100001001
11000110100001110010001001010101010101010001101000
00010000100100000101001010101110100010101010000101
11100100101001001000010000010101010100100100010100
00000010000000101011001111010001100000101010100011
10101010011100001000011000010110011110110100001000
10101010100001101010100101000010100000111011101001
10000000101100010000101100101101001011100000000100
10101001000000010100100001000100000100011110101001
00101001010101101001010100011010101101110000110101
11001010000100001100000010100101000001000111000010
00001000110000110101101000000100101001001000011101
10100101000101000000001110110010110101101010100001
00101000010000110101010000100010001001000100010101
10100001000110010001000010101001010101011111010010
00000100101000000110010100101001000001000000000010
11010000001001110111001001000011101001011011101000
00000110100010001000100000001000011101000000110011
10101000101000100010001111100010101001010000001000
10000010100101001010110000000100101010001011101000
00111100001000010000000110111000000001000000001011
10000001100111010111010001000110111010101101111000

#include <iostream>
#include <queue> 
using namespace std;
char s[4]={'D','L','R','U'};
int b[4][2]={
   
   {1,0},{0,-1},{0,1},{-1,0}}; 

struct node{
    int x;
    int y;
    string a;
    int bushu;
    node(int xx,int yy,string aa,int aaa){
        x=xx;
        y=yy;
        a=aa;
        bushu=aaa;
    }
};
char a[35][55];
bool c[35][55];
queue<node> q;
int guding;
void bfs(int xxx,int yyy){
    c[xxx][yyy]=1;
    q.push(node(xxx,yyy,"",0));
    while(!q.empty()){
        int xx=q.front().x;
        int yy=q.front().y;
        if(xx==29 && yy==49){
            cout<<q.front().a<<endl;
                break;
        }
        for(int i=0;i<4;i++){
            int tx=xx+b[i][0];
            int ty=yy+b[i][1];
            if(tx>=0 && tx<30 && ty>=0 && ty<50 && !c[tx][ty] && a[tx][ty]=='0'){
        
                q.push(node(tx,ty,q.front().a+s[i],q.front().bushu++));
                c[tx][ty]=1;
            }
        }
        q.pop();
    }
}
int main(){
    for(int i=0;i<30;i++){
        for(int j=0;j<50;j++){
            cin>>a[i][j];
        }
    }
    bfs(0,0);           //(0,0)开始, 
    return 0;
}

  D:::::::::::::::::::发现环(并查集,DFS)

题目描述

小明的实验室有 N 台电脑,编号 1⋯N。原本这 N 台电脑之间有N−1 条数据链接相连,恰好构成一个树形网络。在树形网络上,任意两台电脑之间有唯一的路径相连。

不过在最近一次维护网络时,管理员误操作使得某两台电脑之间增加了一条数据链接,于是网络中出现了环路。环路上的电脑由于两两之间不再是只有一条路径,使得这些电脑上的数据传输出现了 BUG。

为了恢复正常传输。小明需要找到所有在环路上的电脑,你能帮助他吗?

输入描述

输入范围:

第一行包含一个整数 N 。

以下 N 行每行两个整数 a,b,表示 a 和 b 之间有一条数据链接相连。

其中, 1≤N≤105,1≤a,b≤N。

输入保证合法。

输出描述

按从小到大的顺序输出在环路上的电脑的编号,中间由一个空格分隔。

输入输出样例

示例

输入

5
1 2
3 1
2 4
2 5
5 3

输出

1 2 3 5

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
int n;
int fa[100005];
bool vis[100005];
int find(int x){
	if(fa[x]==-1) return x;
	return fa[x]=find(fa[x]);
}
vector<int> s[100005];

int qi,end1;
int flage;
bool pl;
int j[100005];
int mm=0;

void print(int step)
{
    sort(j+1,j+1+step);
    for(int i=1;i<=step;i++)
      cout<<j[i]<<" ";
}

void dfs(int x,int step)
{
    vis[x]=1;
    j[step]=x;
    if(x==end1){
      print(step);
      return;
    }
    for(int i=0;i<s[x].size();i++)
        if(!vis[s[x][i]]){
          dfs(s[x][i],step+1);
        }
}


int main(){
	cin>>n;
	memset(fa,-1,sizeof(fa));
	for(int i=0;i<n;i++){
		int a,b;
		cin>>a>>b;
	
		if(find(a)==find(b)){
			qi=a,end1=b;
		}else{
		fa[find(a)]=b;
      	s[a].push_back(b);
		s[b].push_back(a);
    }
	}
	dfs(qi,1);
	return 0;
}

  E:::::::::::::::::::大臣的旅费(双DFS)

题目描述

很久以前,T 王国空前繁荣。为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。

为节省经费,T 国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。

J 是 T 国重要大臣,他巡查于各大城市之间,体察民情。所以,从一个城市马不停蹄地到另一个城市成了 J 最常做的事情。他有一个钱袋,用于存放往来城市间的路费。

聪明的 J 发现,如果不在某个城市停下来修整,在连续行进过程中,他所花的路费与他已走过的距离有关,在走第 x 千米到第 x +1 千米这一千米中( x 是整数),他花费的路费是 x +10 这么多。也就是说走 1 千米花费 11,走 2 千米要花费 23。

J 大臣想知道:他从某一个城市出发,中间不休息,到达另一个城市,所有可能花费的路费中最多是多少呢?

输入描述

输入的第一行包含一个整数 n,表示包括首都在内的 T 王国的城市数。

城市从 1 开始依次编号,1 号城市为首都。

接下来 n -1 行,描述 T 国的高速路( T 国的高速路一定是 n -1 条)。

每行三个整数 Pi​,Qi​,Di​,表示城市 P_iPi​ 和城市 Qi​ 之间有一条高速路,长度为 Di​ 千米。

输出描述:

输出一个整数,表示大臣 J 最多花费的路费是多少。

输入输出样例

示例

输入

5
1 2 2
1 3 1
2 4 5
2 5 4

输出

135

样例说明

大臣 J 从城市 4 到城市 5 要花费 135 的路费。

 这道题好恶心,用dfs最后一个例题,数值较大,开足内存卡内存,不开内存,运行错误,用两遍dfs。

单个:80%

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
int n;
int a[1010][1010];
vector<int> g[10010];
int c;

bool vis[10010];
long long ans;
long long p;
void dfs(int qi,int zhong,long long bu){
	if(bu>ans){
		return;
	} 
	if(qi==zhong){
		ans=min(ans,bu);

		p=max(p,ans);
		return;
	}
	int len=g[qi].size();
	for(int i=0;i<len;i++){
		if(!vis[g[qi][i]]){
			vis[g[qi][i]]=1;
			dfs(g[qi][i],zhong,bu+a[qi][g[qi][i]]);
			vis[g[qi][i]]=0;
		}
	} 
}
int main(){
	cin>>n;
  if(n==1 || n==0){
    cout<<0;
    return 0;
  }
	for(int i=1;i<n;i++){
		int p,q,d;
		cin>>p>>q>>d;
		a[p][q]=a[q][p]=d; 
		g[p].push_back(q);
		g[q].push_back(p);
	}

	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			ans=1e9;
			vis[i]=1;
			dfs(i,j,0);

			vis[i]=0;
			c++;
		}
	}

	cout<<p*10+p*(p+1ll)/2;
	
	return 0;
} 

两遍:


#include <iostream>
#include<vector>
using namespace std;
const int N =100010;

int n;
struct Edge
{
  int id,w;
};
vector<Edge> h[N];
int dist[N];

void dfs(int u,int father,int distance)
{
  dist[u] = distance;

  for(auto node : h[u])   
    if(node.id!= father)   
      dfs(node.id,u,distance + node.w);
}

int main()
{
  scanf("%d",&n);
  for(int i=0;i<n-1;i++)
  {
    int a,b,c;
    scanf("%d%d%d",&a,&b,&c);
    h[a].push_back({b,c});  
    h[b].push_back({a,c});  

  }
  
  dfs(1,-1,0); 
  
  int u=1;
  for(int i=1;i<=n;i++)
    if(dist[i]>dist[u]) u=i;


  dfs(u,-1,0);

  for(int i=1;i<=n;i++)
    if(dist[i]>dist[u]) u=i;
 int v = dist[u];


printf("%lld\n",10*v + v*(v+1ll)/2);
  return 0;
}

  F:::::::::::::::::::最小公倍数(高精度)

题目描述

为什么 1 小时有 60 分钟,而不是 100 分钟呢?这是历史上的习惯导致。

但也并非纯粹的偶然:60 是个优秀的数字,它的因子比较多。

事实上,它是 1 至 6 的每个数字的倍数。即 1,2,3,4,5,6 都是可以除尽 60。

我们希望寻找到能除尽 1 至 n 的的每个数字的最小整数。

不要小看这个数字,它可能十分大,比如 n = 100, 则该数为:

69720375229712477164533808935312303556800

输入描述

输入一个数字 (N<100)。

输出描述

输出出 1 ~ nn 的最小公倍数。

输入输出样例

示例

输入

6

输出

60
 #include<iostream>
#include<cstring>
using namespace std;
int prime[101],ans=0;
void prime_it(){
    for(int i=1;i<=100;i++)prime[i]=i;
    for(int i=2;i<=100;i++){
        for(int j=2;j<=i-1;j++)if(prime[i]%prime[j]==0)prime[i]/=prime[j];
    }
}
int num[101],len=1;
int main(){
    int n;
    prime_it();
    while(cin>>n){
        memset(num,0,sizeof(num));
        num[1]=1,len=1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=len;j++){
                num[j]*=prime[i];
            }
            for(int j=1;j<=len;j++){
                num[j+1]+=num[j]/10;
                num[j]%=10;
            }
            while(num[len+1]){
                len++;
                num[len+1]=num[len]/10;
                num[len]%=10;
            }
        }
        for(int i=len;i>=1;i--)cout<<num[i];
        cout<<endl;
    }
    return 0;
} 

   G:::::::::::::::::::排列叙述(全排列)

题目描述

如果用 a b c d 这 4 个字母组成一个串,有 4!=24 种,如果把它们排个序,每个串都对应一个序号:

abcd 0

abdc 1

acbd 2

acdb 3

adbc 4

adcb 5

bacd 6

badc 7

bcad 8

bcda 9

bdac 10

bdca 11

cabd 12

cadb 13

cbad 14

cbda 15

cdab 16

cdba 17

现在有不多于 10 个两两不同的小写字母,给出它们组成的串,你能求出该串在所有排列中的序号吗?

输入描述

输入一行,一个串。

输出描述

输出一行,一个整数,表示该串在其字母所有排列生成的串中的序号。注意:最小的序号是 0。

输入输出样例

示例

输入

bdca

输出

11
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
string arr;
long long ans=0;
int main(){
	cin>>arr;
	string arr1=arr;
	sort(arr1.begin(),arr1.end());
	if(arr1==arr){
		cout<<0;
		return 0;
	}
	while(next_permutation(arr1.begin(),arr1.end())){
		if(arr1==arr){
			break;
		}
		ans++;
	}
	cout<<ans+1;
	return 0;
}

   H:::::::::::::::::::小朋友崇拜圈(DFS)

题目描述

班里 NN 个小朋友,每个人都有自己最崇拜的一个小朋友(也可以是自己)。

在一个游戏中,需要小朋友坐一个圈,每个小朋友都有自己最崇拜的小朋友在他的右手边。

求满足条件的圈最大多少人?

小朋友编号为 1,2,3,⋯N。

输入描述

输入第一行,一个整数 N(3<N<105)。

接下来一行 N 个整数,由空格分开。

输出描述

要求输出一个整数,表示满足条件的最大圈的人数。

输入输出样例

示例

输入

9
3 4 2 5 3 8 4 6 9

输出

4

样例解释

如下图所示,崇拜关系用箭头表示,红色表示不在圈中。

显然,最大圈是[2 4 5 3] 构成的圈。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M
#include <iostream>
using namespace std;
int a[300005];
bool vis[300005];
int n;
bool p;
int ans;
void dfs(int x,int y,int an){
	if(x==y && an>1){
		ans=max(ans,an);
		return;
	}
	if(!vis[x]){
		vis[x]=1;
		dfs(a[x],y,an+1);
		vis[x]=0;
	}
	
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
			p=false;
			dfs(i,i,0);
	} 
	cout<<ans;
	return 0;
}

   I:::::::::::::::::::出差(Dijkstra

问题描述

A 国有 N 个城市, 编号为 1…N 。小明是编号为 1 的城市中一家公司的员 工, 今天突然接到了上级通知需要去编号为 N 的城市出差。

由于疫情原因, 很多直达的交通方式暂时关闭, 小明无法乘坐飞机直接从 城市 1 到达城市 N, 需要通过其他城市进行陆路交通中转。小明通过交通信息 网, 查询到了M 条城市之间仍然还开通的路线信息以及每一条路线需要花费的 时间。

同样由于疫情原因, 小明到达一个城市后需要隔离观察一段时间才能离开 该城市前往其他城市。通过网络, 小明也查询到了各个城市的隔离信息。(由于 小明之前在城市 1 , 因此可以直接离开城市 1 , 不需要隔离)

由于上级要求, 小明希望能够尽快赶到城市 N, 因此他求助于你, 希望你 能帮他规划一条路线, 能够在最短时间内到达城市 N 。

输入格式

第 1 行: 两个正整数 N,M,N 表示 A 国的城市数量, M 表示末关闭的路 线数量

第 2 行: N 个正整数, 第 i 个整数 Ci​ 表示到达编号为 i 的城市后需要隔离 的时间

第 3…M+2 行: 每行 3 个正整数,u,v,c, 表示有一条城市 u 到城市 v 的 双向路线仍然开通着, 通过该路线的时间为 c

输出格式

第 1 行: 1 个正整数, 表示小明从城市 1 出发到达城市 N 的最短时间(到 达城市 N, 不需要计算城市 N 的隔离时间)

样例输入

4 4
5 7 3 4
1 2 4
1 3 5
2 4 3
3 4 5

样例输出

13

样例说明

评测用例规模与约定

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 512M
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
int n,m;     //n个城市,m条路线 
int geli[10005];   //到每个城市的隔离时间 
int luxian[10005][10005];
int juli[10005];          //到一点的最短距离 
bool vis[10005];
int dj(){
    memset(juli,0x3f3f3f3f,sizeof(juli));
    juli[1]=0;      //距离起点为0 
    geli[1]=0;      //出自己城市不隔离 
    geli[n]=0;      //到达终点不需要隔离 
    for(int i=1;i<=n;i++){
        int s=-1;
        for(int j=1;j<=n;j++){
            if(!vis[j]&&((s==-1)||(juli[j]<juli[s]))){
                s=j;
            }
        } 
        vis[s]=1;
        for(int j=1;j<=n;j++){
        
            juli[j]=min(juli[j],juli[s]+luxian[s][j]+geli[s]);

        }
    }
    return juli[n];
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>geli[i];
    }
    memset(luxian,0x3f3f3f3f,sizeof(luxian));  //无穷大
    for(int i=1;i<=n;i++){
        luxian[i][i]=0;                    //自己到自己为0 
    } 
    for(int i=0;i<m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        luxian[a][b]=luxian[b][a]=min(c,luxian[a][b]);
    }
    int ans=dj(); 
    cout<<ans; 
    return 0;
}

    J:::::::::::::::::::百亿富翁(单调栈)

题目描述

这天小明买彩票中了百亿奖金,兴奋的他决定买下蓝桥公司旁的一排连续的楼房。

已知这排楼房一共有 N 栋,编号分别为 1∼N,第 ii 栋的高度为 hi​。

好奇的小明想知道对于每栋楼,左边第一个比它高的楼房是哪个,右边第一个比它高的楼房是哪个(若不存在则输出 −1)。但由于楼房数量太多,小明无法用肉眼直接得到答案,于是他花了 1 个亿来请你帮他解决问题,你不会拒绝的对吧?

输入描述

第 1 行输入一个整数 N,表示楼房的数量。

第 2 行输入 N 个整数(相邻整数用空格隔开),分别为h1​,h2​,...,hN​,表示楼房的高度。

1≤N≤7×105,1≤hi​≤109。

输出描述

输出共两行。

第一行输出 N 个整数,表示每栋楼左边第一栋比自己高的楼的编号。

第二行输出 N 个整数,表示每栋楼右边第一栋比自己高的楼的编号。

输入输出样例

示例 1

输入

5
3 1 2 5 4 

输出

-1 1 1 -1 4
4 3 4 -1 -1
#include <iostream>
#include <stack>
using namespace std;
int n;
long long a[700005];
stack<int> st;
int l[700005];
int r[700005];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		while(st.size() && a[st.top()]<=a[i]) st.pop();
		if(st.size()){
			l[i]=st.top();
		}else{
			
			l[i]=-1;
		}
		st.push(i);
	}

	while(!st.empty()){
		st.pop();
	}
	
	for(int i=n;i>=1;i--){
		while(st.size() && a[st.top()]<=a[i]) st.pop();
		if(st.size()){
			r[i]=st.top();
		}else{
			r[i]=-1;
		}
		st.push(i);
	}
	for(int i=1;i<=n;i++){
		cout<<l[i]<<' ';
	}
	cout<<endl;
	for(int i=1;i<=n;i++){
		cout<<r[i]<<' ';
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_73731708/article/details/129870479
今日推荐