oj_18.03.25

1.半数集问题

问题描述:

 给定一个自然数n,由n开始可以依次产生半数集set(n)中的数如下。
(1) n∈set(n);
(2) 在n的左边加上一个自然数,但该自然数不能超过最近添加的数的一半;
(3) 按此规则进行处理,直到不能再添加自然数为止。
例如,set(6)={6,16,26,126,36,136}。半数集set(6)中有6 个元素。
注意半数集是多重集。

 对于给定的自然数n,编程计算半数集set(n)中的元素个数。 

个人分析:这是一个递推问题,因为存在关系

因此很轻松地可以编写出代码。这里有一个技巧,就是如果是要求取大量的(比如从1到1000)的半数集的元素个数,用上述递推公式则会重复求取前面求过的半数集的元素个数,因此有个小诀窍就是把已经求好的值放进一个很大的数组比如s[1000],该数组初始化全部元素为0,因此只需要判断s数组中如果元素大于零那么直接可以得到set(n) = s[n]。此外,注意边界条件,set(1) = 1。

代码如下:

int HalfSet(int n){
	if(n == 1) return 1;
	else{
		int sum = 1;
		for(int i=1;i<=n/2;i++) sum += HalfSet(i);
		return sum;
	}
}

2.士兵站队问题

问题描述:

   在一个划分成网格的操场上,n个士兵散乱地站在网格点上。网格点由整数坐标(x,y)表示。士兵们可以沿网格边上、下、左、右移动一步,但在同一时刻任一网格点上只能有一名士兵。按照军官的命令,士兵们要整齐地列成一个水平队列,即排列成(x,y),(x+1,y),,(x+n-1,y)。如何选择y的值才能使士兵们以最少的总移动步数排成一列。请编写程序计算使所有士兵排成一行需要的最少移动步数。

个人分析:题目要求排成水平队列,即最终他们的纵坐标相同,横坐标相互间隔为1。因此,确定纵坐标是比较简单的,只需要求min(|y1-y0|+|y2-y0|+....+|yn-y0|),y0很明显是y1到yn间的中位数(数学证明很简单)。而横坐标我们需要确认队列第一个人的横坐标,然后其他人的坐标就能推出。同理,求出min(|x1-x0|+|x2-(x0+1)|+....+|yn-(y0+n-1)|) ,上式也可以转化为min(|x1-x0|+|(x2-1)-x0|+....+|((xn-(n-1))-x0|),可以先对各点的x坐标做相应处理再求中位数,最后再用公式求出移动步数。

代码如下:

#include 
#include 
using namespace std;

struct point{
	int x;
	int y;
};
/*这是插入排序*/
void SortY(point *p,int len){
	int i,j;  
    int key;  
	for(i = 1;i= 0 && p[j].y > key){  
			p[j+1].y = p[j].y;  
            j = j-1;  
        }  
		p[j+1].y = key;  
    } 

}
void SortX(point *p,int len){
	int i,j;  
    int key;  
	for(i = 1;i= 0 && p[j].x > key){  
			p[j+1].x = p[j].x;  
            j = j-1;  
        }  
		p[j+1].x = key;  
    } 

}

int main(){
	int n;
	cin>>n;
	point *p=new point[n];
	for(int i=0;i>p[i].x>>p[i].y;
	SortY(p,n);
	SortX(p,n);
	int ym = p[n/2].y;
	int movesum = 0;
	for(int i=0;i

3.双色汉诺塔问题

问题描述:

设A、B、C是3 个塔座。开始时,在塔座A 上有一叠共n 个圆盘,这些圆盘自下而上,由大到小地叠在一起。各圆盘从小到大编号为1,2,……,n,奇数号圆盘着蓝色,偶数号圆盘着红色,如图所示。现要求将塔座A 上的这一叠圆盘移到塔座B 上,并仍按同样顺序叠置。在移动圆盘时应遵守以下移动规则:
规则(1):每次只能移动1 个圆盘;
规则(2):任何时刻都不允许将较大的圆盘压在较小的圆盘之上;
规则(3):任何时刻都不允许将同色圆盘叠在一起;

规则(4):在满足移动规则(1)-(3)的前提下,可将圆盘移至A,B,C 中任一塔座上。

试设计一个算法,用最少的移动次数将塔座A 上的n个圆盘移到塔座B 上,并仍按同样

对于给定的正整数n,编程计算最优移动方案。

个人分析:看似很复杂,问题实际与汉诺塔没区别。

代码如下:

#include 
#include 
using namespace std;
void move(int n,char source,char target){
	cout<>disks;
	hanoi(disks,'A','C','B');
}


你可能感兴趣的:(OnlineJudge)