第二回练习

第二次练习

题目

 

1.计数器

**********************************************************************源程序名:                           count.???(C,CPP)                *

*可执行文件名:                       count.exe                       *

*输入文件名:                        count.in                       *

*输出文件名:                        count.out                      *

*********************************************************************

【问题描述】

       一本书的页数为N,页码从1开始编起,请你求出全部页码中,用了多少个0,1,2,3,……,9,其中一个页码不含多余的0,如N = 1234时第5页不是0005,只是5。

【输入】

       一个正整数N(1<=N<=10^9),表示总的页数。

【输出】

       共十行,第K行为数字K-1的个数。

【样例】

       count.in

       11

 

       count.out

       1

       4

       1

       1

       1

       1

       1

       1

       1

       1

 

 代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
#define INF 1e9
#define MIN(x,y) (x<y?x:y)

long long a[10];

void count(long long n){
	long long current, last, tmp = n;
	int factor = 1;
	int len = 0;
	int i;
	while(tmp){
		current = n/factor%10;
		last = n%factor;

		for(i=0; i<=9; ++i){
			a[i] += len*current*factor/10;
		}

		for(i=0; i<current; ++i){
			a[i] += factor;
		}

		a[current] += last+1;

		a[0] -= factor;		//减去多余的0
		factor *= 10;
		len++;
		tmp /= 10;
	}
}

int main(){
	long long n;
	scanf("%I64d", &n);
	memset(a, 0, sizeof(a));
	count(n);
	for(int i=0; i<10; ++i)
		printf("%I64d\n", a[i]);
	return 0;
}

 

2.排队接水

**********************************************************************源程序名:                           water.???(C,CPP)                 *

*可执行文件名:                      water.exe                       *

*输入文件名:                        water.in                        *

*输出文件名:                         water.out                      *

*********************************************************************

【问题描述】

       有N个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这N个人排队的一种顺序,使得N个人的平均等待时间最小。

【输入】

       输入文件一共两行,第一行为N;第二行分别表示第1个人到第N个人每人的接水时间T1,T2,……Tn,每个数据之间有一个空格。

【输出】

       输出文件有两行,第一行为一种排队顺序,即1到N的一种排列(有多种最优解时输出字典序最小的序列);第二行为这种排列方案下的平均等待时间(输出结果精确到小数点后两位,四舍五入)。

【样例】

       water.in

       10

       56 12 1 99 1000 234 33 55 99 812

 

       water.out

       3 2 7 8 1 4 9 6 10 5

       291.90

 

代码:

#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;

struct Tnode{
	double time;
	int label;
}node[1010];

int cmp(const void *a, const void *b){
	struct Tnode e1 = *(struct Tnode *)a;
	struct Tnode e2 = *(struct Tnode *)b;
	if(e1.time==e2.time)	return e1.label - e2.label;
	return e1.time - e2.time;
}

int main(){
	int i, j;
	int n;
	scanf("%d", &n);
	for(i=0; i<n; ++i){
		scanf("%lf", &node[i].time);
		node[i].label = i+1;
	}
	
	qsort(node, n, sizeof(struct Tnode), cmp);
	
	double sum = 0;
	for(i=0; i<n; ++i){
		sum += node[i].time*(n-i-1);
		printf("%d ", node[i].label);
	}
	printf("\n%0.2lf\n", sum/(n*1.0));
	return 0;
}


 

3.最多因子数

**********************************************************************源程序名:                           divisors.???(C,CPP)               *

*可执行文件名:                       divisors.exe                      *

*输入文件名:                         divisors.in                      *

*输出文件名:                         divisors.out                     *

*********************************************************************

【问题描述】

       数学家门喜欢各种类型的有奇怪特性的数。例如,他们认为945是一个有趣的数,因为它是第一个所有约数之和大于本身的奇数。

       为了帮助他们寻找有趣的数,你将写一个程序扫描一定范围内的数,并确定在此范围内约数个数最多的那个数。当范围很大时,我们可能会得到多个答案,此时要将他们都输出来。

【输入】

       只有一行,给出扫描的范围,由下界L和上界U确定,满足2<=L<=U<=4 000。

【输出】

       对于给定的范围,输出该范围内约数最多的数。若有多个,则按升序输出这些数,每个数之间用一个空格隔开。

【样例】

       divisors.in

       1000 2000

 

       divisors.out

       1680

 

 代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
#define INF 1e9
#define MAX(x,y) (x>y?x:y)
#define MIN(x,y) (x<y?x:y)
#define SWAP(x,y) {(x)=(x)^(y);(y)=(x)^(y);(x)=(x)^(y);}

int data[4010];

int main(){
	int i, j;
	
	memset(data, 0, sizeof(data));
	for(i=2; i<4000; ++i){
		for(j=1; j<=4000; ++j){
			if(j%i==0)	data[j]++;
		}
	}
	
	int imax;
	int m, n;
	scanf("%d%d", &m, &n);
	imax= n;
	for(i=m; i<n; ++i)
		if(data[imax]<data[i])	imax = i;
	bool flag = false;
	for(i=m; i<=n; ++i){
		if(data[imax] == data[i]){
			if(flag)	printf(" ");
			flag = true;
			printf("%d", i);
		}	
	}
		
	return 0;
}


 

4.黑白棋游戏

**********************************************************************源程序名:                           game.???(C,CPP)                *

*可执行文件名:                       game.exe                        *

*输入文件名:                         game.in                        *

*输出文件名:                         game.out                       *

*********************************************************************

【问题描述】

       黑白棋游戏的棋盘由一个4*4方格阵列构成。棋盘的每一个方格中放有1枚棋子,共有8枚白色棋子和8枚黑色棋子。这16枚棋子的每一种放置方案都构成一个游戏状态。在棋盘上拥有1条公共边的2个方格称为相邻方格。一个方格最多可有4个相邻方格。在玩黑白棋游戏时,每一步可将任何2个相邻方格中棋子互换位置。对于给定的初始游戏状态和目标游戏状态,编程计算从初始游戏状态变化到目标游戏状态的最短着棋步数。

【输入】

       输入文件共有8行。前四行是初始游戏状态,后四行目标游戏状态。每行4个数分别表示该行放置的棋子颜色。“0”表示白棋;“1”表示黑棋。

【输出】

       输出文件是最少着棋步数N。

【样例】

       game.in

       1 1 1 1

       0 0 0 0

       1 1 1 0

       0 0 1 0

       1 0 1 0

       0 1 0 1

       1 0 1 0

       0 1 0 1

 

       game.out

       4

 

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
#define INF 1e9
#define MIN(x,y) (x<y?x:y)
#define SWAP(x,y) {(x)=(x)^(y);(y)=(x)^(y);(x)=(x)^(y);}
bool visit[16][16][16][16];
int end[4];
int start[4];
int queue[16*16*16*16][5];

void swap_row(int &m, int &n, int pos){
	int first[4], second[4];
	for(int i=0; i<4; ++i){
		first[4-i-1] = m%2;
		m /= 2;
	}
	for(int i=0; i<4; ++i){
		second[4-i-1] = n%2;
		n /= 2;
	}
	
	swap(first[pos], second[pos]);
	
	for(int i=0; i<4; ++i)
		m = m*2 + first[i];
		
	for(int i=0; i<4; ++i)
		n = n*2 + second[i];
}

void swap_col(int &m, int pos){
	int first[4];
	for(int i=0; i<4; ++i){
		first[3-i] = m%2;
		m /= 2;
	}
	SWAP(first[pos], first[pos+1]);
	for(int i=0; i<4; ++i)
		m = m*2 + first[i];
}

bool judge(int m){
	for(int i=0; i<4; ++i)
		if(queue[m][i] != end[i]){
			return false;
		}
	return true;
}

void print(int now){
	static int key = 1;
	printf("Key:%d Start..\n", key);
	key++;
	int first[4][4];
	int i, j, tmp;
	for(i=0; i<4; i++){
		tmp = queue[now][i];
		for(j=0; j<4; j++){
			first[i][3-j] = tmp%2;
			tmp /= 2;
		}
	}
	
	for(i=0; i<4; i++){
		for(j=0; j<4; ++j){
			printf("%d ", first[i][j]);
		}
		printf("\n");
	}
	printf("END....\n\n");
}

int main(){
	int i, j;
	memset(start, 0, sizeof(start));
	memset(end, 0, sizeof(end));
	memset(visit, false, sizeof(visit));
	
	int s[4][4];
	int e[4][4];
	for(i=0; i<4; ++i){
		for(j=0; j<4; ++j){
			scanf("%d", &s[i][j]);
			start[i] = start[i]*2+s[i][j];
		}
//		printf("%d\n", start[i]);
	}
	for(i=0; i<4; ++i){
		for(j=0; j<4; ++j){
			scanf("%d", &e[i][j]);
			end[i] = end[i]*2 + e[i][j];
		}
//		printf("%d\n", end[i]);
	}
	
	visit[start[0]][start[1]][start[2]][start[3]] = true;
	for(i=0; i<4; ++i)
		queue[0][i] = start[i];
	queue[0][4] = 0;
	int head =0, tail = 1;
//	print(head);
//	printf("HELLO \n\n\n");
	while(tail>head){
		if(judge(head)){
			printf("%d\n", queue[head][4]);
			break;
		}
			
		for(i=0; i<3; ++i){
			for(j=0; j<4; ++j){
				swap_row(queue[head][i], queue[head][i+1], j);
				if(!visit[queue[head][0]][queue[head][1]][queue[head][2]][queue[head][3]]){
					visit[queue[head][0]][queue[head][1]][queue[head][2]][queue[head][3]] = true;
					for(int k=0; k<4; ++k)
						queue[tail][k] = queue[head][k];
					queue[tail][4] = queue[head][4]+1;
				//	print(tail);
					//getchar();
					tail++;
				}
				swap_row(queue[head][i], queue[head][i+1], j);
			}
		}
		
		for(i=0; i<4; ++i){
			for(j=0; j<3; ++j){
				swap_col(queue[head][i], j);
				if(!visit[queue[head][0]][queue[head][1]][queue[head][2]][queue[head][3]]){
					visit[queue[head][0]][queue[head][1]][queue[head][2]][queue[head][3]] = true;
					for(int k=0; k<4; ++k)
						queue[tail][k] = queue[head][k];
					queue[tail][4] = queue[head][4]+1;
					tail++;
				}
				swap_col(queue[head][i], j);
			}
		}
		head++;
	}
	
	//printf("%d", queue[head][4]);
	return 0;
}