赞
踩
一、众数问题:
1. 众数问题 问题描述:
给定含有n 个元素的多重集合S,每个元素在S 中出现的次数称为该元素的重数。多重集S 中重数最大的元素称为众数。
例如,S={1,2,2,2,3,5}。
多重集S 的众数是2,其重数为3。
编程任务:
对于给定的由n 个自然数组成的多重集S,编程计算S 的众数及其重数。
数据输入:
输入数据由文件名为input.txt 的文本文件提供。文件的第1 行多重集S 中元素个数n;接下来的n 行中,每行有一个自然数。
结果输出:
程序运行结束时,将计算结果输出到文件output.txt 中。输出文件有2 行,第1 行给出众数,第2 行是重数。
输入文件示例 输出文件示例
input.txt output.txt
6 2
1 3
2
2
2
3
5
代码如下:
- #include <iostream>
- #include <algorithm>//sort()函数头文件
- using namespace std;
- #define N 10000
-
- bool cmp(int a,int b){
- return a<b;
- }
-
- int MaxNum=0; //存储众数大小
- int MaxNumCount=0; //存储众数个数
- int num[10000];
-
- void split(int left,int right){
- if (left >=right) return;//越界跳出
- int FirstLeft=left;//记录初始最左侧
- int FirstRight=right;//记录初始最右侧
- int mid=(left+right)/2;
- for(;left<mid &&num[left]!=num[mid];left++);//找到中位数的左临界
- for(;right>mid&&num[right]!=num[mid];right--);//找到中位数的右临界
- if(MaxNumCount<right-left+1){MaxNum=num[mid];MaxNumCount=right-left+1;}
- //若此中位数个数大于众数个数,则更新
-
- //若中位数左临界左边数字个数小于众数个数,则不需要执行下述操作;中位数右临界数字亦然
- if(left-FirstLeft>MaxNumCount )split(FirstLeft,left-1);
- if(FirstRight-right>MaxNumCount)split(right+1,FirstRight);
- }
-
- int main()
- {
- int n;cin>>n;
- for(int i=0;i<n;i++){
- cin>>num[i];
- }
- sort(num,num+n,cmp);//将数组从小到大排序
- int left0=0;int right0=n-1;
- split(left0,right0);
- cout<<MaxNum<<endl;
- cout<<MaxNumCount<<endl;
- return 0;
- }
二、邮局选址问题
2. 邮局选址问题 问题描述:
在一个按照东西和南北方向划分成规整街区的城市里,n 个居民点散乱地分布在不同的街区中。用x 坐标表示东西向,用y 坐标表示南北向。各居民点的位置可以由坐标(x,y) 表示。街区中任意2 点(x1,y1) 和(x2,y2) 之间的距离可以用数值|x1-x2|+|y1-y2| 度量。
居民们希望在城市中选择建立邮局的最佳位置,使n 个居民点到邮局的距离总和最小。
编程任务:
给定n 个居民点的位置,编程计算n 个居民点到邮局的距离总和的最小值。
数据输入:
由文件input.txt 提供输入数据。文件的第1 行是居民点数n,1<=n<=10000。接下来n 行是居民点的位置,每行2 个整数x 和y,-10000<=x,y<=10000。
结果输出:
程序运行结束时,将计算结果输出到文件output.txt 中。文件的第1 行中的数是n 个居民点到邮局的距离总和的最小值。
输入文件示例 输出文件示例
input.txt output.txt
5 10
1 2
2 2
1 3
3 -2
3 3
代码如下:
- #include <iostream>
- #include <algorithm>//sort()函数头文件
- using namespace std;
- #define N 10000
-
- bool cmp(int a,int b){
- return a<b;
- }
-
- int main()
- {
- int n;cin>>n;
- int X=0, Y=0;//(X,Y)记录邮局位置
- int MinDis=0;
- int x[N],y[N];
- for(int i=0;i<n;i++){
- cin>>x[i]>>y[i];
- }
-
- //街区中任意2 点(x1,y1) 和(x2,y2) 之间的距离可以用数值|x1-x2|+|y1-y2| 度量。
- //所以可将x,y分开计算
- sort(x,x+n,cmp);//排序
- sort(y,y+n,cmp);//排序
- X=x[n/2];Y=y[n/2];
- //下图有解释,为何取[n/2],以及坐标数为奇/偶数此取值皆满足
- //邮局位置找法思想,两边之和大于第三边,x取值必须在以两点为一组,在其连线上
- for(int i=0;i<n;i++){
- int dis1=x[i]-X;int dis2=y[i]-Y;
- if(dis1<0) dis1=-1*dis1;//距离为正值,若作差为负数,则取相反数
- if(dis2<0) dis2=-1*dis2;//距离为正值,若作差为负数,则取相反数
- MinDis=MinDis+dis1+dis2;//求和
- }
- cout<<MinDis<<endl;
- return 0;
- }
三、集合划分问题
3. 集合划分问题 问题描述:
n 个元素的集合{1,2,., n }可以划分为若干个非空子集。例如,当n=4 时,集合{1,2, 3,4}可以划分为15 个不同的非空子集如下:
{{1},{2},{3},{4}},
{{1,2},{3},{4}},
{{1,3},{2},{4}},
{{1,4},{2},{3}},
{{2,3},{1},{4}},
{{2,4},{1},{3}},
{{3,4},{1},{2}},
{{1,2},{3,4}},
{{1,3},{2,4}},
{{1,4},{2,3}},
{{1,2,3},{4}},
{{1,2,4},{3}},
{{1,3,4},{2}},
{{2,3,4},{1}},
{{1,2,3,4}}
其中,集合{{1,2,3,4}} 由1 个子集组成;集合{{1,2},{3,4}},{{1,3},{2, 4}},{{1,4},{2,3}},{{1,2,3},{4}},{{1,2,4},{3}},{{1,3,4},{2}},{{2, 3,4},{1}} 由2 个子集组成;集合{{1,2},{3},{4}},{{1,3},{2},{4}},{{1,4}, {2},{3}},{{2,3},{1},{4}},{{2,4},{1},{3}},{{3,4},{1},{2}} 由3 个子集组成;集合{{1},{2},{3},{4}} 由4 个子集组成。
编程任务:
给定正整数n 和m,计算出n 个元素的集合{1,2,., n }可以划分为多少个不同的由m 个非空子集组成的集合。
数据输入:
由文件input.txt 提供输入数据。文件的第1 行是元素个数n 和非空子集数m。
结果输出:
程序运行结束时,将计算出的不同的由m个非空子集组成的集合数输出到文件output.txt 中。
输入文件示例 输出文件示例
input.txt output.txt
4 3 6
代码如下:
- #include <iostream>
-
- using namespace std;
-
- int num(int n, int m){
- if(n==m||m==1) return 1;
- else{return num(n-1,m-1)+num(n-1,m)*m;}
- }
-
- int main()
- {
- int n,m;cin>>n>>m;
- cout<<num(n,m)<<endl;
- return 0;
- }
对{1,2,3}进行划分:
(1)、1个子集:{1,2,3} 即num(3,1)=1
(2)、2个子集:{1,2},{3} {1,3},{2} {2,3},{1} 即num(3,2)=3
(3)、3个子集:{1},{2},{3} 即num(3,3)=1
对{1,2,3,4}进行划分为3个子集:
(1),在对{1,2,3}划分为两个子集的结果中加入{4}: {1,2},{3},{4} {1,3},{2},{4} {2,3},{1},{4} 此个数为num(3,2)
(2),在对{1,2,3}划分为三个子集的结果中加入元素4:{1,4},{2},{3} {1},{2,4},{3} {1},{2},{3,4} 此个数为num(3,3)*3
综上所述:
num(4,3)=num(3,2)+num(3,3)*3
推广至num(n,m)为: num(n,m)=num(n-1,m-1)+num(n-1,m)*m
且当 n==m或者m==1时,num(n,m)=1
四、输油管道问题
4. 输油管道问题 问题描述:
某石油公司计划建造一条由东向西的主输油管道。该管道要穿过一个有n 口油井的油田。从每口油井都要有一条输油管道沿最短路经(或南或北)与主管道相连。如果给定n 口油井的位置,即它们的x 坐标(东西向)和y 坐标(南北向),应如何确定主管道的最优位置, 即使各油井到主管道之间的输油管道长度总和最小的位置?证明可在线性时间内确定主管道的最优位置。
编程任务:
给定n 口油井的位置,编程计算各油井到主管道之间的输油管道最小长度总和。
数据输入:
由文件input.txt 提供输入数据。文件的第1 行是油井数n,1<=n10000。接下来n 行是油井的位置,每行2 个整数x 和y,-10000<=x,y<=10000 。
结果输出:
程序运行结束时,将计算结果输出到文件output.txt 中。文件的第1 行中的数是油井到主管道之间的输油管道最小长度总和。
输入文件示例 输出文件示例
input.txt output.txt
5 6
1 2
2 2
1 3
3 -2
3 3
代码如下:
- #include <iostream>
- #include <algorithm>
- using namespace std;
- #define N 10000
-
- bool cmp(int a,int b){
- return a<b;
- }
-
- int main()
- {
- int n;cin>>n;
- int X=0, Y=0;//(X,Y)记录邮局位置
- int MinDis=0;
- int x[N],y[N];
- for(int i=0;i<n;i++){
- cin>>x[i]>>y[i];
- }
- sort(x,x+n,cmp);
- sort(y,y+n,cmp);
- X=x[n/2];Y=y[n/2];//邮局位置找法思想,两边之和大于第三边
- //将坐标两两分组,距离两点最近距离肯定在其两点间连线上,取交集即可;
- for(int i=0;i<n;i++){
- int dis1=x[i]-X;int dis2=y[i]-Y;
- if(dis1<0) dis1=-1*dis1;
- if(dis2<0) dis2=-1*dis2;
- MinDis=MinDis+dis2;
- //只需要y坐标距离差的绝对值(与第二题不同,此题为东西走向管道,不需考虑X坐标)
- }
- cout<<MinDis<<endl;
- return 0;
- }
五、 整数因子分解问题
5. | 整数因子分解问题 问题描述: 大于1 的正整数n 可以分解为:n=x1*x2*…*xm。 例如,当n=12 时,共有8 种不同的分解式: 12=12; 12=6*2; 12=4*3; 12=3*4; 12=3*2*2; 12=2*6; 12=2*3*2; 12=2*2*3 。 编程任务: 对于给定的正整数n,编程计算n 共有多少种不同的分解式。 数据输入: 由文件input.txt 给出输入数据。第一行有1 个正整数n (1≤n≤2000000000)。 结果输出: 将计算出的不同的分解式数输出到文件output.txt 。 输入文件示例 输出文件示例 input.txt output.txt 12 8 |
---|
代码如下:
- #include <iostream>
-
- using namespace std;
-
- int factor(int n){
- int sum=0;
- for(int i=n;i>1;i--){
- if(n%i==0){//i是n的因子
- int j=n/i;
- if(factor(j)==0) sum++;
- else{
- sum=sum+factor(j);
- }
- }
- }
- return sum;
- }
-
- int main()
- {
- int n;cin>>n;
- cout<<factor(n)<<endl;
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。