我先给了18年的第三题
搞不太清楚 最短路径和最小生成树的话 可以多看看这个
https://blog.csdn.net/spaceyqy/article/details/39024675
瓜农王大爷去年种西瓜赚了不少钱。看到收入不错,今年他又重新开辟了n个西瓜地。
为了能给他的n个西瓜地顺利的浇上水,对于每个西瓜地他可以选择在本地打井,也可以修管道从另一个瓜地(这个瓜地可能打了井;也可能没打井,他的水也是从其他瓜地引来的)将水引过来。
当然打井和修管道的费用有差别。已知在第i个西瓜地打井需要耗费wi元,在第i、j个西瓜地之间修管道需要耗费pi,j元。
现在的问题是:王大爷要想使所有瓜地都被浇上水,至少需要花费多少钱(打井与修管道的费用和)?
由于瓜地较多,王大爷无法选择在哪些(个)瓜地打井,哪些西瓜地之间修管道。
请你编程帮王大爷做出决策,求出最小费用。
(1<=N<=300,1<=wi<=100000;pi,i=0,1<=pi,j=pj,i<=100000)
input
第1行,一个正整数n,代表西瓜地的数量。
以下n行,依次给出整数w1…wn(每块西瓜地的打井费用)。
紧接着是一个n*n的整数矩阵,矩阵的第i行第j列的数代表pi,j(两块西瓜地之间建立管道的费用)。每行的两个数之间有一个空格隔开。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
//瓜农王大爷去年种西瓜赚了不少钱。看到收入不错,今年他又重新开辟了n个西瓜地。
//为了能给他的n个西瓜地顺利的浇上水,对于每个西瓜地他可以选择在本地打井,也可以修管道从另一个瓜地(这个瓜地可能打了井;也可能没打井,他的水也是从其他瓜地引来的)将水引过来。
//当然打井和修管道的费用有差别。已知在第i个西瓜地打井需要耗费wi元,在第i、j个西瓜地之间修管道需要耗费pi,j元。
//现在的问题是:王大爷要想使所有瓜地都被浇上水,至少需要花费多少钱(打井与修管道的费用和)?
//由于瓜地较多,王大爷无法选择在哪些(个)瓜地打井,哪些西瓜地之间修管道。
//请你编程帮王大爷做出决策,求出最小费用。
//这道题和我之前写过的类似,就是求最短路径,可以将打井的钱,当做是从原点到该水管的距离,这样就增加了一些距离
//可以创建一个数组来存储第一位是起点,第二位是终点,值是对应距离
//用到并查集
int a[100];//用来存对应点的祖宗
int zuzong(int x){
//找到某个点的祖宗
if(a[x]==x)
return x;
else
return zuzong(a[x]);
}
bool check(int x,int y){
//判断两点是否同一个祖宗,也就是在不在同一个集合
return zuzong(x)==zuzong(y);
}
void merge_1(int x,int y){
//合并两个点到同一个祖宗,前提是他们不是同一个祖宗
a[zuzong(x)]=zuzong(y);
}
int dis[100][100];
int i,j;
int n;//西瓜地的数量
struct Y{
int s,e,dis;//对应起点,终点,和对应距离
}Gua[100];
bool cmp(Y a,Y b){
return a.dis<b.dis;//距离从小到大排序
}
int main(){
scanf("%d",&n);
int temp[100][100];//中间数组
for(i=1;i<=n;i++){
Gua[i].s=0;
Gua[i].e=i;
scanf("%d",&Gua[i].dis);
}
int m=n+1;//因为前面n个点已经记录了好了距离,所以需要从第n+1个点开始
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
scanf("%d",&temp[i][j]);
if(i<j){
Gua[m].s=i;
Gua[m].e=j;
Gua[m].dis=temp[i][j];//修管道的费用,只输出单方向的,让无向图变成有向的
m++;
}
}
//对数组进行花费从小到大排序
sort(Gua+1,Gua+m+1,cmp);//n是西瓜地数量,c是边数,默认从小到大
//再将每个点,默认祖宗初始设置为自己
for(i=0;i<=n;i++)
a[i]=i;
//开始合并
int sum=0;
for(i=1;i<=m;i++)//一共m条边
if(!check(Gua[i].s,Gua[i].e)){//没有合并,那就合并,并且记录对应花费
sum+=Gua[i].dis;
merge_1(Gua[i].s,Gua[i].e);
}
printf("%d",sum);
}
第一题
Problem Description
有一群人去电影院看电影。但电影院有个很奇怪的规定:成人只能分到数字奇数座位号,未满18岁的儿童只能分到数字为偶数的座位号。
Input
输入共有n个人去看电影(1<=n<1000),接下来输入n个人的座位号,每个座位号用空格隔开
Output
依次输出此次看电影成人的人数以及成人在所有人中所占的比例、未成年人的人数以及未成年人在所有人中所占的比例,计算出的比例保留两位小数,每个输出用空格隔开
Sample Input
8 13 12 10 8 3 24 21 19
Sample Output
4 0.50 4 0.50
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
//第一题
//Problem Description
//有一群人去电影院看电影。但电影院有个很奇怪的规定:成人只能分到数字奇数座位号,未满18岁的儿童只能分到数字为偶数的座位号。
//Input
//输入共有n个人去看电影(1<=n<1000),接下来输入n个人的座位号,每个座位号用空格隔开
//Output
//依次输出此次看电影成人的人数以及成人在所有人中所占的比例、未成年人的人数以及未成年人在所有人中所占的比例,计算出的比例保留两位小数,每个输出用空格隔开
//Sample Input
//8 13 12 10 8 3 24 21 19
//Sample Output
//4 0.50 4 0.50
int main(){
int i,n;//输入的人数
int sum1=0;
int sum2=0;
int a[100];
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&a[i]);
if((a[i]%2)==0)
sum2++;
else
sum1++;
}
printf("%d %.2f %d %.2f",sum1,(1.0*sum1)/n,sum2,(1.0*sum2)/n);
}
Problem Description
有一个大容器,现在向其中加入若干铅锤的木板,每个木板的顶端坐标记为(i,yi),如图
Input
输入共加入n个木板(1<=n<1000),接下来输入n个数字表示加入的n个木板的高度,每个高度用空格隔开
Output
输出该容器最大能装多少体积的水(容器不允许倾斜)
Sample Input
8 1 8 6 4 5 3 7 2
Sample Output
35
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
//第二题,给n模板,输入n个值代表模板的高度,求最大容积
//我感觉就直接暴力,两次for循环,i从0-n-1 然后J 从i+1 到n-1 直接求最大值
int main(){
int i,j,n;
scanf("%d",&n);
int a[100];
for(i=0;i<n;i++)
scanf("%d",&a[i]);
int v,mmax=0;
for(i=0;i<n;i++)
for(j=i+1;j<n;j++){
v=(j-i)*min(a[i],a[j]);
if(v>mmax)
mmax=v;
}
printf("%d",mmax);
}
Problem Description
有一群人,现在告诉你他们之间的朋友关系。若A与B是朋友,B是C的朋友,则A与C也是朋友。朋友关系都是双向的,即A与B是朋友,B与A也是朋友。那么A、B、C就在同一个“朋友圈”
Input
首先输入n,m表示有n个人,m对关系(1<=n<2000),接下来有m行每一行表示一对关系(输入每个数字代表一个人)
Output
输出在当前输入关系的情况下“朋友圈”的数量
Sample Input
8 7
1 2
2 4
4 1
5 7
4 3
6 2
7 8
Sample Output
2
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
//第四题有点像是连通图, 求连通图的个数。那就是用dfs或者bfs,或者是用并查集,然后用一个coun++
struct Y{
int s,e;
}fri[100];
int a[100];
int zuzong(int x){
if(x==a[x])
return x;
else
return zuzong(a[x]);
}
bool check(int x,int y){
return zuzong(x)==zuzong(y);
}
void merge_1(int x,int y){
a[zuzong(x)]=zuzong(y);
}
int main(){
int n,m;//n个人,m种关系
int i,c=1;//初始值为1,假设都连通
scanf("%d%d",&n,&m);
for(i=0;i<m;i++){
scanf("%d%d",&fri[i].s,&fri[i].e);
}
//先赋初始值
for(i=1;i<=n;i++)
a[i]=i;
for(i=0;i<m;i++){
if(!check(fri[i].s,fri[i].e)){//就是靠并查集来记录,有哪些是不一样的
merge_1(fri[i].s,fri[i].e);
}
}
//这个时候已经全都分好类了,然后就开始筛选吧,
//我想到一个办法就是对数组进行排序,然后找到不一样的值
//创建一个数组来存祖宗
int temp[100];
for(i=1;i<=n;i++)
temp[i]=zuzong(i);
//for(i=1;i<=n;i++)
//printf("%d ",temp[i]);
sort(temp+1,temp+1+n);
int flag=temp[1];
for(i=2;i<=n;i++){
if(temp[i]!=flag){
flag=temp[i];
c++;
}
}
printf("%d",c);
}