第三次练习

题目

 

1. 翻硬币

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

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

*输入文件名:                        coin.in                         *

*输出文件名:                        coin.out                        *

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

【问题描述】

小明正在玩一个“翻硬币”的游戏。

桌上放着排成一排的若干硬币。我们用 * 表示正面,用 o 表示反面(是小写字母,不是零)。

比如,可能情形是:**oo***oooo

如果同时翻转左边的两个硬币,则变为:oooo***oooo

现在小明的问题是:如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢?

我们约定:把翻动相邻的两个硬币叫做一步操作;

【输入】

       两行等长的字符串,分别表示初始状态和要达到的目标状态(每行的长度<=1000)

【输出】

       一个整数,表示最小操作步数;(如果达不到目标状态则输出-1)

【样例】

       coin.in

       **********

      o****o****

 

       coin.out

       5

 

代码:

#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);}

char str[1010];
bool start[1010], end[1010];

int main(){
	int i;
	int len;
	
	memset(start, false, sizeof(start));
	memset(end, false, sizeof(end));
	scanf("%s", str);

	len = strlen(str);
	for(i=0; i<len; ++i)
		if(str[i] == 'o')	start[i] = true;
		
	scanf("%s", str);

	len = strlen(str);
	for(i=0; i<len; ++i)
		if(str[i] == 'o')	end[i] = true;

	int step = 0;
	
	for(i=0; i<len-1; ++i){
		if(start[i] != end[i]){
			step++;
			start[i] = !start[i];
			start[i+1] = !start[i+1];
		}
	}
	if(start[i]!=end[i])
		step = -1;
	printf("%d\n", step);
	return 0;
}


 

2.分数转换

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

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

*输入文件名:                        fraction.in                       *

*输出文件名:                         fraction.out                      *

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

【问题描述】

       任何两个有理数整数相除都可以表示为无限循环小数的形式。例如:1/7 = 0.142857142... 是个无限循环小数。本题的要求是给出一个分子和分母都是有理整数的数,求这个分数的小数表示。

【输入】

       一个分数,分子和分母用“/”隔开。(分子分母均为正数,且均不超过1000)

【输出】

       等于输入分数的小数或无限循环小数(循环节用方括号括起)

【样例】

       fraction0.in

       1/5

 

       fraction0.out

       0.2

 

       fraction1.in

       7/6

 

       fraction1.out

       1.1[6]

 

代码:

#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 c;
int d[100], leave[100];		//d:存储小数部分,leave存储余数 
int flag;
int main(){
	int i,j;
	int a, b;
	scanf("%d/%d", &a, &b);
	c = a/b;				//整数部分 
	flag = false;
	if(a%b==0)	flag = 1;	//判断是否小数部分 
	
	int first = 0;
	int n;
	int tmp = a%b;
	i = 0;
	leave[0] = a%b;
	while(tmp&&flag!=2){
		tmp *= 10;
		d[i] = tmp/b;
		tmp %= b;
		
		i++;
		leave[i] = tmp;
		for(j=0; j<i; ++j){
			if(leave[j] == tmp){	//找到循环的开始 
				first = j;			//存储循环的开始坐标 
				flag = 2;			//表示有循环节 
				break;
			}
		}
	}
	n = i;
	
	if(flag == 1)	printf("%d\n", c);
	else{
		printf("%d.", c);
		if(flag == 0)	{
			for(i=0; i<n; ++i)
				printf("%d", d[i]);
			printf("\n");
		}
		
		else{
			for(i=0; i<first; ++i)
				printf("%d", d[i]);
			printf("[");
			for(i=first; i<n;++i)
				printf("%d", d[i]);
			printf("]\n");
		}
	}
	return 0;
}


 

3.书的复制

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

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

*输入文件名:                         book.in                        *

*输出文件名:                         book.out                       *

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

【问题描述】

       现在要把M本有顺序的书分给K个人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比如不能把第一、第三、第四本书给同一个人抄写。

       现在请你设计一种方案,使得复制时间最短。复制时间为抄写页数最多的人用去的时间。

【输入】

       第一行两个整数M,K;(1<=K<=M<=500)

       第二行M个整数,第i个整数表示第i本书的页数。

【输出】

       共K行,每行两个正整数,第i行表示第i个人抄写的书的起始编号和终止编号。K行的起始编号应从小到大排列,如果有多种解,则尽可能让前面的人少抄写。

【样例】

       book.in

       9 3

       1 2 3 4 5 6 7 8 9

 

       divisors.out

       1 5

       6 7

       8 9

 

 代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
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 book[510];
int f[510][510];
int show[510][2];
int sum[510];

int main(){
	int M,K;
	scanf("%d%d", &M,&K);
	memset(book, 0, sizeof(book));
	for(int i=1; i<=M; ++i){
		scanf("%d", &book[i]);
	}
	
	int i,j,t;
	memset(f, 0, sizeof(f));
	memset(sum, 0, sizeof(sum));
	for(i=1; i<=M; ++i)
		sum[i]  = sum[i-1]+book[i];
	
	for(i=1; i<=M; ++i)
		f[1][i] = sum[i];
	
	for(i=2; i<=K; ++i){
		for(j=1; j<=M; ++j){
			f[i][j] = INF;
			for(t=1; t<=j-1; ++t){
				f[i][j] = MIN(MAX(f[i-1][t], sum[j]-sum[t]), f[i][j]);
			}
		}
	}
	
	j = K;
	int sum;
	for(i=M; i>0; ){
		sum = book[i];
		show[j][1] = i;
		while(sum <= f[K][M]){
			--i;
			if(i==0)	break;
			sum += book[i];
		}
		i++;
		show[j--][0] = i;
		i--;
	}
	
	for(i=1; i<=K; ++i){
		printf("%d %d\n", show[i][0], show[i][1]);
	}
	return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值