题目
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;
}