文章目录
- 概要
- 13 求阶乘结果0的个数
- 17 T的倍数N
- 22 *约瑟夫环2
- 26 阶乘最后的非0位
- 34 繁殖问题
- 37 黑色星期五
- 44 三艘船
- 49 *修理牛棚
- 52 序列
- 54 等差数列
- 57 **求N!
- 66 菱形输出
- 72 *数字金字塔
- 76 *最大效益
- 77 螺旋方阵
- 78 方块转换
- 90 字符串中找整数
- 91 乒乓球
- 103 *分割数字并排序
- 104 A == B ?
- 105 *母牛制造的回文
- 109 **大实数加法
- 110 *考试排名
- 116 扑克牌
- 119 挤牛奶
- 121 分糖果
- 124 分数化小数
- 128 *汉诺塔问题的第m步
- 10 分解质因数
- 13 **2n皇后问题
- 14 芯片测试
- 16 8皇后·改
- 19 *排队打水问题
- 26 *聪明的美食家
- 33 *线段和点
- 35 快速幂
- 43 最少操作数
- 45 和最大子序列
- 小结
概要
东华oj精选复试上机题,带*表示较重要题目。
13 求阶乘结果0的个数
提示:循环
问题描述 :
编写一个程序,求出N!的末尾含有多少个0。
提示:在乘积中,末尾有多少个0,主要看各乘数的素数因子中有多少个2和5,每一个2和5的结合将给末尾贡献一个0。而乘数中因子2的个数远多于因子5的个数,因此,就计算各乘数中因子5的个数即可。
输入说明 :
你的数据需要从标准输入设备(通常为键盘)中读入多组测试数据。每组输入数据由一行组成,每行由一个正整数N组成,N小于等于100000,在行首和行尾没有多余的空格。
输出说明 :
对每组测试数据,你的程序需要向标准输出文件(通常为启动该程序的文本终端)依次输出一组对应的答案。所有数据前后不要输出多余的空行,两组数据之间也不要输出多余的空行。每组输出数据由一行组成,每行由一个整数组成,在行首和行尾不要输出多余的空格。
输入范例 :
5
100000
输出范例 :
1
24999
int main() {
int a = 0,j = 0, nums[100] = { 0 };
while (scanf("%d", &a) != -1) {
int num = 0;
for (int i = a;i > 1;i--,i=a) {
while (i % 5 == 0) {
num++;
i = i / 5;
}
a--;
}
printf("%d\n", num);
}
}
17 T的倍数N
提示:循环
问题描述 :
明明学习数学已经有很多年了,对各种各样的数学问题都有研究。有一天,明明的爸爸问明明说:“明明,你觉得你对数字敏感吗?”明明毫不犹豫地回答:“那当然,非常敏感。”于是明明的爸爸就说:“好,那我问你一个问题,如果有一个个位数为7的自然数N,把它的个位数移到最高位,其余各位均右移一位(如127变成712),要求这样得到的一个新的数是原数的T倍。若我现在把自然数T告诉你,你能求出最小的符合条件的自然数N吗?” 明明觉得这个问题很简单,只要按从小到大的顺序把所有是7结尾的自然数找出来,然后交换位置,再除一下,看看倍数是不是T倍就可以了。明明回答爸爸说:“这个问题很简单,来考我吧。”于是明明的爸爸就给了明明一个数字2,让他开始动手寻找。但是,使明明意想不到的是,他找了很久很久,始终没有找到想要的那个数,而当他到查到1000007时,需要的那个数还是没有出现,于是就放弃了。他觉得靠手工查找的话,是无法快速找到的。因此,明明求助于你,请你帮他写一个程序,来解决这个相当棘手的问题。但是他也给了你另外一个条件,如果找到超过1000000时还是没有找到需要的那个数的话,就停止寻找。 明明的问题可以归结为:对于一个个位数为7的自然数N,把它的个位数移到最高位,其余各位均右移一位,要求这样得到的一个新的数是原数的T倍。现给出这个自然数T,求满足这个要求的最小的自然数N。若在[1, 1000000] 的范围内没有找到N,则输出“No”。
输入说明 :
你写的程序要求从标准输入设备(通常,键盘为标准输入设备)中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行仅有一个自然数T(1≤T≤9)。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备(通常,显示屏为标准输出设备)中。每组运算结果输出一个自然数N或“No”,不包括双引号。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。
输入范例 :
5
3
8
输出范例 :
142857
No
No
#include<stdio.h>
#include<math.h>
int main() {
int times;
int flag = 0;
while (scanf("%d", ×) != -1) {
flag = 0;
for (int i = 0;i <= 1000000;i += 10) {
int s = i, final = i, n = 0;
while (s > 0) {
s /= 10;
n++;
}
final /= 10;
final += 7 * pow(10, n - 1);
if (n == 0)final += 7;
if ((i + 7) * times == final) {
printf("%d\n", i + 7);
flag = 1;
break;
}
}
if (flag == 0) {
printf("No\n");
}
}
}
22 *约瑟夫环2
提示:循环
问题描述 :
明明是一名公安局的谈判专家,专门负责和绑匪谈判。有一次,明明接到一个特殊的任务,他赶到了案发现场,发现有k个绑匪绑架了k个人质,于是明明就开始和绑匪进行谈判。绑匪提出了一个非常特殊的要求,如果明明能够回答出这个问题,那绑匪将释放所有的人质;否则,绑匪就要撕票。 绑匪的问题是这样:绑匪把人质和自己围成一个圈,把人质从1开始编号,一直编到k,然后绑匪自己从k+1开始编号,一直编到2k。现在从编号1开始,每次从其中选出第m个人(隔m-1选出一个人)出列,然后绑匪要求明明选定这个m值,且m值要尽量的小,使得最先出列的k个人都是绑匪。 例如:有3个坏人和3个人质,他们排成一圈,其中编号1到3的为人质,编号4到6的为坏人,如下: 1、2、3、4、5、6; 明明要选定m=5时,能够满足绑匪的要求。因为: 第一轮,从1开始数,编号5出列,剩下的人为: 1、2、3、4、6; 第二轮,从6开始数,编号4出列,剩下的人为: 1、2、3、6; 第三轮,从6开始数,编号6出列,剩下的人为: 1、2、3; 这样所有的绑匪都先出列,明明可以成功地救出所有的人质。 如果明明能够找到这个m值,那么所有的人质都想获救,否则的话,后果不堪设想。明明意识到了问题的严重,这个问题对他来说十分地棘手。于是明明想到了你,你是一名程序设计专家,明明想让你用程序来解这个问题,救出所有的人质。 明明的问题可以归结为:假设有k个人质和k个绑匪围成一圈。人质的编号从1到k,绑匪的编号从k+1到2k。从编号1开始,每次从其中选出第m个人(隔m-1选出一人)出列。希望求出m的最小值,使得最先出列的k个人都是绑匪,即都是编号从k+1到2k的人。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅一行,每组测试数据有一个整数k(1≤k≤10),表示人质的人数和绑匪的人数。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个整数m,即明明要选定的那个数。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。 注:通常,显示屏为标准输出设备。
输入范例 :
1
2
3
5
输出范例 :
2
7
5
169
#include<iostream>
#include<string>
using namespace std;
int main() {
int n;
string str;
while (cin >> n) {
str.insert(0, n, 'f');
str.insert(n, n, 'w');
for (int i = 1;;i++) {
string s = str;
int start = (i - 1) % s.size();
bool isok = true;
if (s.at(start) == 'f') {
isok = false;
continue;
}
s.erase(start, 1);
while (s.find('w')!=-1) {
start = (start + i - 1) % s.size();
if (s.at(start) == 'f') {
isok=false;
break;
}
s.erase(start, 1);
}
if (isok) {
cout << i << endl;
break;
}
}
str.clear();
}
}
26 阶乘最后的非0位
提示:循环
问题描述 :
N的阶乘写作N!表示小于等于N的所有正整数的乘积。阶乘会很快的变大,如13!就必须用32位整数类型来存储,70!即使用浮点数也存不下了。你的任务是找到阶乘最后面的非零位。举个例子,5!=12345=120所以5!的最后面的非零位是2,7!=1234567=5040,所以最后面的非零位是4。
输入说明 :
一个不大于1000的整数N。
输出说明 :
共一行,输出N!最后面的非零位。
输入范例 :
7
输出范例 :
4
int main() {
int a;
scanf("%d", &a);
int num = 1;
int count2 = 0;
int count5 = 0;//7 3 3
for (int i = a;a > 1;a--) {
i = a;
while (i % 5 == 0) {
i /= 5;
count5++;
}
while (i % 2 == 0) {
i /= 2;
count2++;
}
num = num * i % 10;
}
if (count2 - count5 > 0) {
for (int i = 0;i < count2 - count5;i++) {
num = num * 2 % 10;
}
}
else if (count2 - count5 < 0) {
num = num * count5 % 10;
}
printf("%d", num);
}
34 繁殖问题
提示:一维数组
问题描述 :
有一家生化所,一月份引入一对新生的小白鼠。这对小白鼠生长两个月后,在第三、第四、第五个月各繁殖一对新小白鼠,在第六个月停止繁殖,在第七个月则死亡。新生的小白鼠也如此繁殖。问在第N个月时,活的小白鼠有多少对?
输入说明 :
你的程序需要从标准输入设备(通常为键盘)中读入多组测试数据。每组输入数据由一行组成,其中只有一个整数N(0 < N ≤ 50)。两组输入数据间无空行。
输出说明 :
对于每组测试数据,你的程序需要向标准输出设备(通常为启动该程序的文本终端)输出一行,其中只有一个整数,即第N个月时活的小白鼠有几对,所有数据前后没有多余的空行,两组数据之间也没有多余的空行。
输入范例 :
1
2
3
4
5
6
7
8
30
输出范例 :
1
1
2
3
5
7
10
15
67066
int main()
{
int i, a[60] = { 1,1,2,3,5,7,10,15 }, n;
for (i = 8;i < 55;i++)
{
a[i] = a[i - 2] + a[i - 3] + a[i - 4];
}
while (scanf("%d", &n) != -1)
{
printf("%d\n", a[n - 1]);
}
return 0;
}
37 黑色星期五
提示:一维数组
问题描述 :
13号又是星期五是一个不寻常的日子吗? 13号在星期五比在其他日少吗?为了回答这个问题,写一个程序来计算在n年里13 日落在星期一,星期二…星期日的次数.这个测试从1900年1月1日到 1900+n-1年12月31日.n是一个非负数且不大于400.
这里有一些你要知道的: 1900年1月1日是星期一. 4,6,11和9月有30天.其他月份除了2月都有31天.闰年2月有29天,平年2月有28天.
输入说明 :
一个整数n(1<= n <= 400).
输出说明 :
七个在一行且相分开的整数,它们代表13日是星期六,星期日,星期一…星期五的次数.
输入范例 :
20
输出范例 :
36 33 34 33 35 35 34
#include<iostream>
using namespace std;
int main() {
int n;
cin >> n;
int year = 1900, month = 1;
int nums[7] = { 0 };
nums[5]++;
int priDay = 5;
while (year != 1900 + n) {
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
priDay = (priDay + 31) % 7;
}
else if (month == 4 || month == 6 || month == 9 || month == 11) {
priDay = (priDay + 30) % 7;
}
else if (month == 2) {
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
priDay = (priDay + 29) % 7;
}
else {
priDay = (priDay + 28) % 7;
}
}
month++;
nums[priDay]++;
if (month == 13) {
month = 1;
year++;
}
}
nums[priDay]--;
int j = 4;
for (int i = 0;i < 7;i++) {
j = (j + 1) % 7;
if (i == 6)cout << nums[j];
else cout << nums[j] << " ";
}
}
44 三艘船
提示:一维数组
问题描述 :
明明由于工作的关系,经常需要坐船到某地出差办事。久而久之,明明就对这两地之间船的班次情况相当了解,他会根据办事的具体情况选择不同班次的船出行。这两地的船一共分为三个班次:特快船、快船、慢船,三个班次的船在同一天的0点从港口出发,并沿着同一路线匀速航行,只是它们到达目的地的时刻不同。 你作为明明的好朋友,有一次和明明在闲聊,问到他出差时船的航行距离有多少时,明明没有正面回答你这个问题,而只是把三艘船(特快、快、慢)的速度,以及它们到达目的地的时间是几点钟(并不知道分别是哪一天,只知道三艘船都在100天以内到达了终点)告诉了你,要你推算出两地间的距离长度。你作为一位程序设计专家,自然不会被明明的这个问题所难倒,于是你决定写一个程序,来求解这个看似困难其实简单的问题。 明明的问题可以归结为:给出三艘船的速度,以及它们到达目的地时是几点钟(并不知道分别是哪一天,只知道三艘船都在100天以内到达了终点),求两地间的距离到底有多少。若有多组解,只输出最小的那组解。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据占二行,第一行有3个正整数a、b、c,代表3艘船的到达港口那天的时间是几点钟(0≤a、b、c≤23)。第二行有3个正整数d、e、f代表3艘船的速度(0<d、e、f<30000),速度的单位是单位距离每小时。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果由一个整数构成,代表路程的长度,若有多组解,只输出最小的那组解。每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。
输入范例 :
4 2 20
5 10 13
18 12 21
6 9 12
输出范例 :
260
540
#include<stdio.h>
int main() {
int a, b, c, d, e, f;
while (scanf("%d %d %d %d %d %d", &a, &b, &c, &d, &e, &f) != -1) {
int s1 = d * 24, s2 = e * 24, s3 = f * 24;
int isFind = 0;
for (int i = 0;i < 100;i++) {
for (int j = 0;j < 100;j++) {
if (s1 * i + a * d == s2 * j + b * e) {
int z = 0;
while (1) {
if (s3 * z + c * f == s1 * i + a * d) {
printf("%d\n", s3 * z + c * f);
isFind = 1;
break;
}
if (s3 * z + c * f > s1 * i + a * d) {
break;
}
z++;
}
}
if (isFind == 1)break;
}
if (isFind == 1)break;
}
}
}
49 *修理牛棚
提示:一维数组
问题描述 :
在一个暴风雨的夜晚,农民约翰的牛棚的屋顶、门被吹飞了。 好在许多牛正在度假,所以牛棚(牛棚的总数S:1<= S<=200)没有住满。 剩下的牛一个紧挨着另一个被排成一行安置在有屋顶的牛棚来过夜。 所以有些牛棚里有牛,有些没有。
所有的牛棚有相同的宽度,且宽度设为1。 因为有些门遗失,农民约翰需要架起新的木板作为门。 他的新木材供应者将会供应他任何他想要的长度,但是供应者只能提供有限数目的木板。 农民约翰想将他购买的木板总长度减到最少。
计算拦住所有有牛的牛棚所需木板的最小总长度。
输出所需木板的最小总长度作为的答案。
说明:拦住一个牛棚需要的木板长度为1,拦住相邻的三个牛棚则需要木板长度为3。
比如有牛的牛棚编号为:
3 5 8 10 11
并且只能使用两块木板,
则第一块木板从3到5,长度为3,
第二块木板从8到11,长度为4,
因此,需要木板的总长度为7。
输入说明 :
第 1 行: M 和 C(用空格分开)
第 2 到 C+1行: 每行包含一个整数,表示牛所占的牛棚的编号。
其中:
可能买到的木板最大的数目:M(1<= M<=50);
需要安置的牛的数目C(1<= C <=S)
安置后牛所在的牛棚的编号stall_number(1<= stall_number <= S)。
输出说明 :
单独的一行包含一个整数表示所需木板的最小总长度
输入范例 :
3 5
2
4
6
8
7
输出范例 :
5
#include<iostream>
#include<algorithm>
using namespace std;
int main() {
int wood, cow;
cin >> wood >>cow;
int nums[100] = { 0 };
int cowgap[100] = { 0 };
for (int i = 0;i < cow;i++) {
cin >> nums[i];
}
if (wood >= cow) {
cout << cow << endl;
return 0;
}
sort(nums, nums + cow);
for (int i = 0;i < cow - 1;i++) {
cowgap[i] = nums[i + 1] - nums[i] - 1;
}
sort(cowgap, cowgap + cow - 1);
int room = 0,sum = 1;
for (int i = 1;i < wood;i++) {
room += cowgap[cow - 1 - i];
}
sum += nums[cow - 1] - nums[0] - room;
cout << sum << endl;
}
52 序列
提示:一维数组
问题描述 :
明明的爸爸经常用做游戏的方法启发明明对数学的兴趣。有一次,明明爸爸准备了许多盒子和球,他要和明明做一个放球的游戏。
游戏如下:要将k个小球依次装入到若干个盒子中去(可以使用的盒子数不限)。
小球装入盒子的规则如下:
1)第一个盒子不能为空。
2)依次装入各个盒子的球数必须严格递增。例如:当k=8时,装入方法有1,2,5或1,3,4。
3)装入的盒子数尽可能多。
4)所有相邻盒子的球数之差的绝对值之和最小。
如上例中:装入法1,2,5,则差的绝对值之和为(2-1)+(5-2)=4。装入法1,3,4,则差的绝对值之和为(3-1)+(4-3)=3。因此应该采用后一种装法。
明明明白了规则以后,就兴致盎然地玩起了游戏。起先明明玩得很有劲,每次都能顺利的找出最佳的装小球的方法。但是随着小球数量的增多,装小球的方法也就变得越来越多,明明就需要花更多的时间才能找到最佳的装球方法,这使得明明有些犯难了。于是明明想到了你,他想请你帮他写一个程序,他把小球的数量告诉你,而你的程序用来计算装小球的方法。
明明的问题可以归结为:告诉你小球的数量k,然后通过程序计算出盒子装小球的最佳方法。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行有一个整数k(1 ≤k ≤10000),即小球的个数。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一串整数,即表示依次放入各个盒子里的小球的个数,每两个数字之间用一个‘,’分隔。每组运算结果单独占一行,其行首和行尾都没有任何空格或其他任何字符,每组运算结果与其后一组运算结果之间没有任何空行或其他任何字符,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行或其他任何字符。 注:通常,显示屏为标准输出设备。
输入范例 :
1
8
10
输出范例 :
1
1,3,4
1,2,3,4
#include<iostream>
using namespace std;
int main()
{
int n,a[200];
while (cin >> n)
{
int t = 0,j=0, i = 1;
while (t< n)
{
if (t + i > n) //如果超出了范围那么就把多的分到前面去
{
int m = j - 1; int k = 1,b=n-t;
for (; k <=b; )
{
a[m]+=1;
t++;
m--;
k++;
}
}
else //先保持递增次序
{
t += i;
a[j++] = i;
i++;
}
}
for (int i = 0; i < j-1; i++)
{
cout << a[i] << ",";
}
cout << a[j-1] << endl;
}
return 0;
}
54 等差数列
提示:一维数组
问题描述 :
一个等差数列是一个能表示成a, a+b, a+2b,…, a+nb (n=0,1,2,3,…) 在这个问题中a是一个非负的整数,b是正整数。
写一个程序来找出在双平方数集合S中长度为n的等差数列。双平方数集合是所有能表示成p2+q2的数的集合。
输入说明 :
第一行: N(3<= N<=25),要找的等差数列的长度。 第二行: M(1<= M<=250),搜索双平方数的上界0 <= p,q <= M。
输出说明 :
如果没有找到数列,输出`NONE’。
如果找到了,输出一行或多行, 每行由两个整数组成:a,b 这些行应该先按b排序再按a排序(均为升序)。
将不会有多于10,000个等差数列。
输入范例 :
5 7
输出范例 :
1 4
37 4
2 8
29 8
1 12
5 12
13 12
17 12
5 20
2 24
#include<iostream>
using namespace std;
int main()
{
bool arr[100000] = { 0 };
int n, m;
cin >> n >> m;
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= m; j++) {
arr[i * i + j * j] = true;
}
}
bool isFind = false;
for (int b = 1; b <= m * m; b++) {
for (int a = 0; a <= m * m; a++) {
int i;
for (i = 0; i < n; i++) {
if (arr[a + i * b] == false) break;
}
if (i == n) {
isFind = true;
cout << a << " " << b << endl;
}
}
}
if (!isFind) cout << "NONE" << endl;
}
57 **求N!
提示:一维数组
问题描述 :
给你一个整数N(0 ≤ N ≤ 10000),你的任务是计算并输出 N!
输入说明 :
输入多行,每行一个N。
输出说明 :
对于每个输入N,在一行中输出N!
行首与行尾为空格,两组输出之间无空行。
输入范例 :
2
1
100
输出范例 :
2
1
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
#include<iostream>
using namespace std;
int main() {
int n;
int arr[10000] = { 0 };
arr[0] = 1;
while (cin >> n) {
if (n == 0 || n == 1) {
cout << '1' << endl;
continue;
}
if (n == 2) {
cout << '2' << endl;
continue;
}
int length = 1;
int next = 0;
for (int i = 2;i <= n;i++) {
for (int j = 0;j < length;j++) {
int temp = i * arr[j] + next;
arr[j] = temp % 10;
next = temp / 10;
if (next != 0 && j == length - 1) {
length++;
}
}
}
for (int i = length - 1;i >= 0;i--) {
cout << arr[i];
arr[i] = 0;
}
arr[0] = 1;
cout << endl;
}
}
66 菱形输出
提示:图形
问题描述 :
明明这次又碰到问题了:
给定一个正整数N,明明的爸爸让他输出一个以Z开始的菱形,以后依次为Y,X…,
比如当N等于1的时候输出图形:
Z
当N等于2的时候,输出图形:(Y前没有空格,Z、X和W前一个空格)
Z
Y X
W
当N等于3的时候,输出图形(Z前两个空格,Y、X前一个空格,W前没有空格…):
Z
Y X
W V
U T
S
明明发现当N很大的时候就不是很容易了,所以找到了你,希望你编写一个程序帮助他
明明的问题可以归结为:输入一个正整数N,输出一个以Z开始的菱形,以后依次为Y,X…。
请尝试定义函数,该函数的功能是输出以上图形的一行。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行仅包括一个正整数n(1≤n≤7)。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组输出一个以Z开始的菱形,具体格式参照样例输出。每组运算结果与其后一组运算结果之间有一个空行,最后一组运算结果之后没有空行。 注:通常,显示屏为标准输出设备。
输入范例 :
1
3
输出范例 :
Z
Z
Y X
W V
U T
S
/*
x
x x
x x
x x
1 3 0
2 2 1
3 1 3
4 0 5
5 1 3
6 2 1
7 3 0
i-x=n
y=(2*n-i-1)*2-1
x=4-n;
y=(n-1)*2-1;
*/
void func(int n) {
char x = 'Z';
int lines = n * 2 - 1;
for (int i = 1;i <= lines;i++) {//每行
if (i <= lines / 2 + 1) {
for (int j = 0;j < n - i;j++) {
cout << " ";
}
cout << x;
x--;
if (i == 1 || i == lines) {
cout << endl;
continue;
}
for (int j = 0;j < (i - 1) * 2 - 1;j++) {
cout << " ";
}
cout << x;
x--;
cout << endl;
}
else {
for (int j = 0;j < i - n;j++) {
cout << " ";
}
cout << x;
x--;
if (i == 1 || i == lines) {
cout << endl;
continue;
}
for (int j = 0;j < (2 * n - i - 1) * 2 - 1;j++) {
cout << " ";
}
cout << x;
x--;
cout << endl;
}
}
}
int main() {
int n;
while (cin >> n) {
func(n);
cout << endl;
}
}
72 *数字金字塔
提示:贪心算法/二维数组
问题描述 :
考虑在下面被显示的数字金字塔(第n行有n列)。写一个程序来计算从最高点开始在底部任意处结束的路径经过数字的和的最大。每前进一步可以走到它的正下方或者右下方(往下一行、往右一列)的位置。
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
在上面的样例中,从7 到 3 到 8 到 7 到 5 的路径产生了最大和:30
输入说明 :
第一个行包含 R(1<= R<=1000) ,表示行的数目。后面每行为这个数字金字塔特定行包含的整数。所有的被供应的整数是非负的且不大于100。
输出说明 :
输出仅一行,包含那个可能得到的最大的和。
输入范例 :
6
7
3 8
8 1 0
2 7 4 100
4 5 2 6 5
3 2 5 8 7 6
输出范例 :
129
#include<iostream>
using namespace std;
int main() {
int n;
cin >> n;
int nums[100][100] = { 0 }, values[100][100] = { 0 };
for (int i = 0;i < n;i++) {
for (int j = 0;j <= i;j++) {
cin >> nums[i][j];
}
}
values[0][0] = nums[0][0];
for (int i = 1;i < n;i++) {
for (int j = 0;j <= i;j++) {
if (j == 0)values[i][j] = values[i - 1][j] + nums[i][j];
else if (i == j)values[i][j] = values[i - 1][j - 1] + nums[i][j];
else {
values[i][j] = (values[i - 1][j] > values[i - 1][j - 1])?(values[i - 1][j] + nums[i][j]) : (values[i - 1][j - 1] + nums[i][j]);
}
}
}
int max = 0;
for (int i = 0;i < n;i++) {
max = max > values[n - 1][i] ? max : values[n - 1][i] ;
}
cout << max << endl;
}
76 *最大效益
提示:贪心算法/二维数组
问题描述 :
明明的爸爸开了一家小公司,公司里有5名职员。今天,公司接待了5位客户。明明的爸爸知道,和任何一位客户谈判并签下合同都要花一整天的时间,而他又希望在一天之内,和这5位客户都签好合同。因此,明明的爸爸要求公司里的5名职员分别与1位客户谈判。
明明的爸爸也知道,这5名职员和5位客户的性格各不相同。因此,不同的职员与不同的客户谈判,会给公司带来不同的经济效益。他现在要做出一个决策,让5名职员分别与哪位客户谈判,才能让公司今天的总经济效益最大。
明明的爸爸首先做了一张5行5列的效益表,如下所示:
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
在这张效益表中,每行代表一名公司职员,每列代表一个客户,每行中的5个数字就表示了当该行所代表的公司职员和每位客户谈判时所能产生的效益。明明的爸爸就要通过这张效益表来决定哪位职员与哪位顾客谈判,然后能够使公司的效益最大。就拿上面这张表来看,由于无论哪位职员与哪位客户谈判,所产生的效益都是1,因此最大的效益就是5。这是最简单的一种情况,但是当效益表里的数字变得复杂,就很难进行选择,到底哪种组合方式才是最优的。因此明明的爸爸求助于你,帮助他解决这个问题。
明明的爸爸的问题可以归结为:给你一张5行5列的效益表,表中的数字均为大于等于0的整数,要求在这张表中选出5个数字,使这5个数字的和最大。(注:这5个数字分别来自表中的不同行不同列,即同一行只能选择一个数字,同一列也只能选择一个数字。)
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据。每组测试数据占5行;每行包含5个正整数;第i行的第j个正整数Aij代表第i名职员与第j位客户谈判能为公司带来的经济效益(0≤Aij≤100, 1≤i,j≤5)。每组测试数据与其后一组测试数据之间没有任何空行;第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个整数s,即这一天中公司的最大可能总经济效益。例如:当测试数据中的所有Aij(1≤i,j≤5)均为1时,运算结果s应为5。输出时,每组运算结果s单独占一行,其行首和行尾都没有任何空格或其他任何字符;每组运算结果与其后一组运算结果之间没有任何空行或其他任何字符,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行或其他任何字符。
注:通常,显示屏为标准输出设备。
输入范例 :
98 97 96 95 94
1 2 3 4 5
11 22 33 44 55
66 77 88 99 1
13 32 64 7 86
输出范例 :
318
#include<iostream>
using namespace std;
int main() {
int nums[5][5] = { 0 };
while (cin >> nums[0][0]) {
int max = 0;
int sum = 0;
int maxi, maxj;
for (int i = 0;i < 5;i++) {
for (int j = 0;j < 5;j++) {
if (i == 0 && j == 0)continue;
cin >> nums[i][j];
}
}
for (int times = 0;times < 5;times++) {
for (int i = 0;i < 5;i++) {
for (int j = 0;j < 5;j++) {
if (max < nums[i][j]) {
max = nums[i][j];
maxi = i;
maxj = j;
}
}
}
sum += max;
max = 0;
for (int i = 0;i < 5;i++) {
nums[i][maxj] = 0;
}
for (int j = 0;j < 5;j++) {
nums[maxi][j] = 0;
}
}
cout << sum << endl;
}
}
77 螺旋方阵
提示:二维数组
问题描述 :
明明在上学的时候,参加数学兴趣班。在班上,老师介绍了一种非常有趣的方阵,称之为螺旋方阵。该方阵一共由n×n个正整数构成(我们称之为n阶螺旋方阵),即共有n行n列。
方阵中的数字从1开始递增,数字的排序规则是从左上角出发由1开始排序,并按顺时针方向旋进,即先排最外面的一圈,然后排里面的一圈,以此类推,直到排到最后一个数为止。
例如一个4阶的螺旋方阵,一共有4×4=16个正整数构成,数字从1递增到16,最后排出来的方阵如下:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
明明回家后想自己动手构造这样的螺旋方阵。他从n=1开始构造,但是他发现当n越来越大时,螺旋方阵的复杂性就越高,然后构造出来的方阵就越容易出错。为了降低构造方阵的出错率,提高构造速度,明明就求助于你,请你帮他写一个程序,来构造螺旋方阵。 明明的问题可以归结为:给你一个正整数n,请你按题目描述中所述的方法,构造出n阶的螺旋方阵。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行仅有一个正整数n(1≤n≤10),即所要构造的螺旋方阵的阶数。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个n阶的螺旋方阵,方阵中的数字用一个空格隔开,具体形式请参考输出样例。每组运算结果与其后一组运算结果之间有一个空行,最后一组运算结果之后没有空行。 注:通常,显示屏为标准输出设备。
输入范例 :
9
4
输出范例 :
1 2 3 4 5 6 7 8 9
32 33 34 35 36 37 38 39 10
31 56 57 58 59 60 61 40 11
30 55 72 73 74 75 62 41 12
29 54 71 80 81 76 63 42 13
28 53 70 79 78 77 64 43 14
27 52 69 68 67 66 65 44 15
26 51 50 49 48 47 46 45 16
25 24 23 22 21 20 19 18 17
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
#include<iostream>
using namespace std;
int main() {
int n;
int nums[100][100] = { 0 };
while (cin >> n) {
int maxi = n, maxj = n, mini = 0, minj = 0;
int i = 0, j = 0;
int count = 1;
bool addi = true;
bool addj = true;
bool iAct = false;
for (int times = 0;times < n * n;times++) {
nums[i][j] = count++;
if (i == 0 && j == 0) {
j++;
continue;
}
if (addi && iAct)i++;
if (!addi && iAct)i--;
if (addj && !iAct)j++;
if (!addj && !iAct)j--;
if (i == maxi - 1 && iAct && addi) {
maxi--;
addi = false;
iAct = !iAct;
}
else if (j == maxj - 1 && !iAct && addj) {
maxj--;
addj = false;
iAct = !iAct;
}
else if (i == mini + 1 && iAct && !addi) {
mini++;
addi = true;
iAct = !iAct;
}
else if (j == minj && !iAct && !addj) {
minj++;
addj = true;
iAct = !iAct;
}
}
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
if (j == n - 1)cout << nums[i][j];
else cout << nums[i][j] << " ";
}
cout << endl;
}
}
}
78 方块转换
提示:图形
问题描述 :
一块N x N(1=<N<=10)正方形的黑白瓦片的图案要被转换成新的正方形图案。
写一个程序来找出将原始图案按照以下列转换方法转换成新图案的最小方式:
#1:转90度:图案按顺时针转90度。
#2:转180度:图案按顺时针转180度。
#3:转270度:图案按顺时针转270度。
#4:反射:图案在水平方向翻转(形成原图案的镜像)。
#5:组合:图案在水平方向翻转,然后按照#1-#3之一转换。
#6:不改变:原图案不改变。
#7:无效转换:无法用以上方法得到新图案。
如果有多种可用的转换方法,请选择序号最小的那个。
比如:
转换前:
@-@
---
@@-
转换后:
@-@
@--
--@
这种转换采取#1(按顺时针转90度)即可。
注意:图案中的字符“@”和“-”在转90度后,还是“@”和“-”。不要认为“-”转90度后变成“|”。
输入说明 :
第一行: 单独的一个整数N。
第二行到第N+1行: N行,每行N个字符(不是’@‘就是’-’);这是转换前的正方形。
第N+2行到第2*N+1行: N行,每行N个字符(不是’@‘就是’-’);这是转换后的正方形。
输出说明 :
单独的一行包括1到7之间的一个数字(在上文已描述)表明需要将转换前的正方形变为转换后的正方形的转换方法。
输入范例 :
3
--@
--@
---
@@-
---
---
输出范例 :
3
#include<iostream>
using namespace std;
int n;
char nums[10][10] = { 0 };
char change[10][10] = { 0 };
char test[10][10] = { 0 };
bool func1() {
int count = 0;
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
if (nums[i][j] == change[j][n - 1 - i])count++;
}
}
if (count == n * n)return true;
return false;
}
bool func2() {
int count = 0;
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
if (nums[i][j] == change[n - 1 - i][n - 1 - j])count++;
}
}
if (count == n * n)return true;
return false;
}
bool func3() {
int count = 0;
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
if (nums[i][j] == change[n - 1 - j][i])count++;
}
}
if (count == n * n)return true;
return false;
}
bool func4() {
int count = 0;
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
if (nums[i][j] == change[i][n - 1 - j])count++;
}
}
if (count == n * n)return true;
return false;
}
bool func5() {
int count = 0;
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
test[i][j] = nums[i][n - 1 - j];
}
}
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
if (test[i][j] == change[j][n - 1 - i])count++;
}
}
if (count == n * n)return true;
else count = 0;
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
if (test[i][j] == change[n - 1 - i][n - 1 - j])count++;
}
}
if (count == n * n)return true;
else count = 0;
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
if (test[i][j] == change[n - 1 - j][i])count++;
}
}
if (count == n * n)return true;
return false;
}
bool func6() {
int count = 0;
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
if (nums[i][j] == change[i][j])count++;
}
}
if (count == n * n)return true;
return false;
}
int main() {
cin >> n;
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
cin >> nums[i][j];
}
}
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
cin >> change[i][j];
}
}
if (func1())cout << "1";
else if (func2())cout << "2";
else if (func3())cout << "3";
else if (func4())cout << "4";
else if (func5())cout << "5";
else if (func6())cout << "6";
else cout << "7";
}
90 字符串中找整数
提示:字符串
问题描述 :
对于一个字符串,编程找出其中的所有整数。例如,字符串“a12bc34d05”,其中有整数12、34、5。
输入说明 :
程序输入包括多行,每一行都是一串字符,字符串长度不超过500。字符串中的字符只有字母与数字。
输出说明 :
程序输出为多行,每行第一个数代表所对应的字符串中整数的总个数。紧跟其后的依次是每个整数,数和数之间有一个空格。行与行之间没有多余空行,行首行尾没有多余空格。
输入范例 :
a12bc034d5
12886668&78711
abcdefghijklmn
输出范例 :
3 12 34 5
2 12886668 78711
0
#include<stdio.h>
#include<string.h>
int main()
{
char a[500];
while(gets(a))//写入字符串
{
int b[50]={0};
int j=0;
for(int i=0;i<strlen(a);i++)
{
if(a[i]<='9'&&a[i]>='0'){
while(a[i]<='9'&&a[i]>='0')//将数字放入数组b中
{
int k=a[i]-'0';//将字符转化为数字,根据ASCII
b[j]=k+b[j]*10;
i++;
}
j++;
}
}
printf("%d",j);
for(int i=0;i<j;i++)
{
printf(" %d",b[i]);
}
printf("\n");
}
}
91 乒乓球
提示:字符串
问题描述 :
国际乒联主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及。其中11分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役。明明就是其中一位,他退役之后走上了乒乓球研究工作,意图弄明白11分制和21分制对选手的不同影响。在开展他的研究之前,明明首先需要对他多年比赛的统计数据进行一些分析,所以需要你的帮忙。 (注:11(21)分制,在一局比赛中,选手A先得到11(21)分且此时领先选手B 2分或2分以上时,则选手A赢得此局;若当双方打成10(20)平后,则先多得2分的一方为胜方,赢得此局。)
明明通过以下方式进行分析,首先将比赛每个球的胜负列成一张表,然后分别计算在11分制和21分制下,双方的比赛结果(截至记录末尾)。一局比赛的开始比分为0比0。 比如现在有这么一份记录,(其中W表示明明获得一分,L表示明明的对手获得一分):
WWWWWWWWWWWWWWWWWWWWWWLW
在11分制下,此时比赛的结果是明明第一局11比0获胜,第二局11比0获胜,正在进行第三局,当前比分1比1。
在21分制下,此时比赛结果是明明第一局21比0获胜,正在进行第二局,当前比分2比1。
再如有这么一份记录,(其中W表示明明获得一分,L表示明明的对手获得一分):
WLWLWLWLWLWLWLWLWLWLWLWLWL
在11分制下,此时比赛的结果是明明和对手打成13比13,这局比赛仍没有分出胜负,因为任何一方都没有领先其对手2分。
在21分制下,此时比赛的结果是明明和对手打成13比13,这局比赛仍在进行中。
由于明明参加过多年的比赛,比赛的数据量相当庞大,如果仅仅使用手工统计,在短时间内统计出结果对于明明来说是相当困难的。因此明明求助于你,希望你能写一个程序,帮助他快速地统计出结果来。
明明的问题可以归结为:给你一系列的比赛数据(WL形式),分别按照11分制和21分制的比赛规则进行统计,然后输出统计结果。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每行包括一串有W、L和E组成比赛结果,其中W表示明明得一分,L表示明明的对手得一分,E表示该组测试数据的结束,也就是说E后面的W、L应该忽略,无需处理。每行的长度不会超过30个字符。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。
每组运算结果由两部分组成,其中第一部分是11分制下的结果,第二部分是21分制下的结果,两部分之间由一个空行分隔。
每部分由若干行组成,每一行对应一局比赛的比分(按比赛信息输入顺序),每局的比分按如下形式表示:m:n,其中m表示明明的得分,n表示明明的对手的得分,m、n之间用一个冒号隔开。
输出时,每组运算结果与其后一组运算结果之间有一个空行,第一组运算结果前面以及最后一组运算结果后面没有任何空行或其他任何字符。 注:通常,显示屏为标准输出设备。
输入范例 :
WWWWWWWWWWLLLLLLLLLLL
WWWWWWWWWLLLLLLLLLE
LLLLLLLLLLLLLLLLLE
输出范例 :
13:11
6:9
19:20
0:11
0:6
0:17
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main() {
string c;
vector<string> result1;
vector<string> result2;
int win1 = 0,win2=0;
int fail1 = 0,fail2=0;
bool isE = false;
while (cin>>c) {
for (int i = 0;i < c.size();i++) {
switch (c[i]) {
case 'W':
win1++;
win2++;
break;
case 'L':
fail1++;
fail2++;
break;
case 'E':
isE = true;
if (win1 != 0 || fail1 != 0) {
result1.push_back(to_string(win1) + ":" + to_string(fail1));
}
if (win2 != 0 || fail2 != 0) {
result2.push_back(to_string(win2) + ":" + to_string(fail2));
}
for (int j = 0;j < result1.size();j++) {
cout << result1[j] << endl;
}
cout << endl;
for (int j = 0;j < result2.size();j++) {
cout << result2[j] << endl;
}
win1 = 0;
win2 = 0;
fail1 = 0;
fail2 = 0;
result1.clear();
result2.clear();
}
if (isE) {
isE = false;
c.clear();
cout << endl;
break;
}
if ((abs(win1 - fail1) >= 2 && (win1 >= 11 || fail1>=11))||(win1>=10&&fail1>=10&& abs(win1 - fail1) >= 2)) {
result1.push_back(to_string(win1) + ":" + to_string(fail1));
win1 = 0;
fail1 = 0;
}
if ((abs(win2 - fail2) >= 2 && (win2 >= 21 || fail2 >= 21)) || (win2 >= 20 && fail2 >= 20 && abs(win2 - fail2) >= 2)) {
result2.push_back(to_string(win2) + ":" + to_string(fail2));
win2 = 0;
fail2 = 0;
}
}
}
}
103 *分割数字并排序
提示:字符串
问题描述 :
输入一行数字,如果我们把这行数字中的‘5’都看成空格,那么就得到一行用空格分割的若干非负整数(可能有些整数以‘0’开头,这些头部的‘0’应该被忽略掉,除非这个整数就是由若干个‘0’组成的,这时这个整数就是0)。
你的任务是:对这些分割得到的整数,依从小到大的顺序排序输出。
输入说明 :
输入包含多组测试用例,第一行,测试案例个数,每组输入数据只有一行数字(数字之间没有空格),这行数字的长度不大于1000。
输入数据保证:分割得到的非负整数不会大于100000000;输入数据不可能全由‘5’组成。
输出说明 :
对于每个测试用例,输出分割得到的整数排序的结果,相邻的两个整数之间用一个空格分开,每组输出占一行。
输入范例 :
2
0051231232050775
4000050005045453356356456454564567677686564654
输出范例 :
0 77 12312320
0 4 4 4 4 33 63 64 64 64 646 40000 67677686
#include <iostream>
#include<algorithm>
#include<string>
using namespace std;
int main() {
int n;
cin >> n;
for (int i = 0;i < n;i++) {
string s;
multiset<int> numbers;
bool isBegin = true;
int begin = 0;
int end = 0;
cin >> s;
while (s.find('5') != -1) {
int pos = s.find('5');
if (pos == s.size() - 1) {
s = s.erase(s.size() - 1, 1);
break;
}
string p = (s.substr(0, pos));
while (p.find('0') == 0 && p.size()!=1) {
p.erase(0, 1);
}
if (p.size() != 0) {
numbers.insert(stoi(p));
}
s = s.substr(pos + 1);
}
while (s.find('0') == 0 && s.size() != 1) {
s.erase(0, 1);
}
numbers.insert(stoi(s));
for (multiset<int>::iterator it = numbers.begin();it != numbers.end();it++) {
if (it == --numbers.end()) {
cout << *it;
}
else {
cout << *it << " ";
}
}
cout << endl;
}
}
104 A == B ?
提示:stold
问题描述 :
给你两个非负实数A和B,如果A等于B,输出 “YES”, 否则输出"NO"
输入说明 :
第一行N,表示有N组测试数据。
以下N行,每行两个非负实数 A和B。每个实数不超过1000位,且可能在前面和后面有0存在。
输出说明 :
对于每组测试数据,如果A和B相等则输出 “YES”, 否则输出 “NO”。
每组测试数据占一行,两组测试数据之间无空行。行首与行尾均无空格。
输入范例 :
2
100.0 00100
0100.1234576 00000000100.123457
输出范例 :
YES
NO
#include <bits/stdc++.h>
using namespace std;
/*
stoi: string型变量转换为int型变量
stol: string型变量转换为long型变量
stoul:string型变量转换为unsigned long型变量
stoll: string型变量转换为long long型变量(常用)
stoull:string型变量转换为unsigned long long型变量
stof: string型变量转换为float型变量
stod: string型变量转换为double型变量(常用)
stold:string型变量转换为long double型变量
*/
int main() {
int n;
cin >> n;
for (int i = 0;i < n;i++) {
string a, b;
cin >> a >> b;
long double x = stold(a);
long double y = stold(b);
if (x == y) {
cout << "YES" << endl;
}
else {
cout << "NO" << endl;
}
}
}
105 *母牛制造的回文
提示:字符串
问题描述 :
据说如果你给无限只母牛和无限台巨型便携式电脑(有非常大的键盘),那么母牛们会制造出世上最棒的回文。你的工作就是去这些牛制造的奇观(最棒的回文)。在寻找回文时不用理睬那些标点符号、空格(但应该保留下来以便做为答案输出),只用考虑字母’A’-‘Z’和’a’-‘z’。要你寻找的最长的回文的文章是一个不超过20,000个字符的字符串。我们将保证最长的回文不会超过2,000个字符(在除去标点符号、空格之前)。
输入说明 :
一个不超过20,000个字符的文件。
输出说明 :
输出的第一行应该包括找到的最长的回文的长度。
下一个行或几行应该包括这个回文的原文(没有除去标点符号、空格), 把这个回文输出到一行或多行(如果回文中包括换行符)。如果有多个回文长度都等于最大值,输出那个前出现的。
输入范例 :
Confucius say: Madam, I’m Adam.
输出范例 :
11
Madam, I’m Adam
#include<iostream>
#include<string>
using namespace std;
string s;
int maxNum = 0;
int maxi;
void DFS(int n,int m) {
if (m == 0) {
DFS(n, m + 1);
}
else if (n >= s.size()) {
return;
}
else if ((n - m <= 0 || n + m >= s.size() || s[n - m] != s[n + m])) {
if(maxNum < m) {
maxNum = m;
maxi = n - m;
}
DFS(n + 1, 0);
}
else if (s[n - m] == s[n + m]) {
DFS(n, m + 1);
}
}
int main() {
string oriString;
char x;
while (cin.get(x)) {
oriString.push_back(x);
if ((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z')) {
if (x >= 'A' && x <= 'Z') {
x = x - ('A'-'a');
}
s.push_back(x);
}
}
DFS(0, 0);
int begin = 0;
int pos = 0,m = 0;
while (m != maxi + maxNum * 2 ) {
if ((oriString[pos] >= 'a' && oriString[pos] <= 'z') || (oriString[pos] >= 'A' && oriString[pos] <= 'Z')) {
m++;
}
if (m == maxi + 1) {
begin = pos;
}
pos++;
}
cout << maxNum * 2 - 1 << endl;
cout << oriString.substr(begin + 1, pos - begin - 1) << endl;
}
109 **大实数加法
提示:字符串
问题描述 :
给你两个正的实数A和B,你的任务是计算出A+B的值。
输入说明 :
本题目包含T组测试数据。
每一组测试数据在一行里面包含两个长度不大于400的正实数A和B,A和B均无多余的前导0。
输出说明 :
对于每一组测试数据,请在一行里面输出输出A+B的值,行首与行尾均无空格。
运算结果最后的0(比如1.400)不需要输出(输出为1.4)。
输入范例 :
3
1.1 2.9
1.1111111111 2.3444323343
1 1.1
输出范例 :
4
3.4555434454
2.1
#include<iostream>
#include<string>
using namespace std;
string addBig(string a, string b) {
string finalStr;
if (a.size() > b.size()) {
int x = a.size() - b.size();
b.insert(0, x, '0');
}
else if (a.size() < b.size()) {
int x = b.size() - a.size();
a.insert(0, x, '0');
}
int length = a.size();
bool isNextAdd = false;
for (int i = length - 1;i >= 0;i--) {
int sum = a[i] - '0' + b[i] - '0';
if (isNextAdd) {
sum++;
isNextAdd = false;
}
if (sum >= 10) {
sum -= 10;
isNextAdd = true;
}
finalStr.insert(0,1,(char)(sum + '0'));
}
if (isNextAdd)finalStr.insert(0, 1, '1');
return finalStr;
}
void apart(string s, string& num, string& decNum) {
if (s.find('.') == -1) {
num = s;
decNum = "0";
}
else {
int pos = s.find('.');
num = s.substr(0, pos);
decNum = s.substr(pos + 1);
}
}
string addBig(string a, string b,bool &isLeftAdd) {
string finalStr;
if (a.size() > b.size()) {
int x = a.size() - b.size();
b.insert(b.size(), x, '0');
}
else if (a.size() < b.size()) {
int x = b.size() - a.size();
a.insert(a.size(), x, '0');
}
int length = a.size();
bool isNextAdd = false;
for (int i = length - 1;i >= 0;i--) {
int sum = a[i] - '0' + b[i] - '0';
if (isNextAdd) {
sum++;
isNextAdd = false;
}
if (sum >= 10) {
sum -= 10;
isNextAdd = true;
}
finalStr.insert(0, 1, (char)(sum + '0'));
}
if (isNextAdd)isLeftAdd = true;
else isLeftAdd = false;
return finalStr;
}
int main() {
int n;
cin >> n;
for (int i = 0;i < n;i++) {
string a, b;
string numA, decNumA, numB, decNumB;
bool isDecAdd = false, isLeftAdd = false;
cin >> a >> b;
apart(a, numA, decNumA);
apart(b, numB, decNumB);
string decSum = addBig(decNumA, decNumB,isDecAdd);
string leftSum;
if (isDecAdd) {
leftSum = addBig(addBig(numA, "1"),numB);
}
else {
leftSum = addBig(numA, numB);
}
if (decSum == "0") {
cout << leftSum << endl;
}
else {
cout << leftSum << '.' << decSum << endl;
}
}
}
110 *考试排名
提示:结构体
C++编程考试使用的实时提交系统,具有即时获得成绩排名的特点。它的功能是怎么实现的呢?
我们做好了题目的解答,提交之后,要么“AC”,要么错误,不管怎样错法,总是给你记上一笔,表明你曾经有过一次错误提交,因而当你一旦提交该题“AC”后,就要与你算一算帐了,总共该题错误提交了几回。虽然你在题数上,大步地跃上了一个台阶,但是在耗时上要摊上你共花去的时间。特别是,曾经有过的错误提交,每次都要摊上一定的单位时间分。这样一来,你在做出的题数上,可能领先别人很多,但是,在做出同样题数的人群中,你可能会在耗时上处于排名的劣势。
例如:某次考试一共8题(A,B,C,D,E,F,G,H),每个人做的题都在对应的题号下有个数量标记,负数表示该学生在该题上有过的错误提交次数,但到现在还没有AC,正数表示AC所耗的时间,如果正数a跟上一对括号,里面有个整数b,那就表示该学生提交该题AC了,耗去了时间a,同时,曾经错误提交了b次(如果b为0则没有括号及b),因此对于下述输入数据:
若每次错误提交的罚分为20分,即每错误提交一次,在总耗时时增加20分钟,则其排名从高到低应该是这样的:
Josephus 5 376
John 4 284
Alice 4 352
Smith 3 167
Bob 2 325
Bush 0 0
输入说明 :
输入数据的第一行是考试题数n(1≤n≤12)以及单位罚分数m(10≤m≤20),每行数据描述一个学生的用户名(不多于10个字符的字串)以及对所有n道题的答题现状,其描述采用问题描述中的数量标记的格式,见上面的表格,提交次数总是小于100,AC所耗时间总是小于1000。
学生数小于100。
输出说明 :
将这些学生的考试现状,输出一个实时排名。实时排名显然先按AC题数的多少排,多的在前,再按时间分的多少排,少的在前,如果凑巧前两者都相等,则按名字的字典序排,小的在前。每个学生占一行,输出名字(10个字符宽,左对齐),做出的题数(2个字符宽,右对齐)和时间分(4个字符宽,右对齐)。除上面所描述的为了对齐输出的空格外,名字、题数和时间分相互之间有一个空格。
输入范例 :
8 20
Smith -1 -16 8 0 0 120 39 0
John 116 -2 11 0 0 82 55(1) 0
Josephus 72(3) 126 10 -3 0 47 21(2) -2
Bush 0 -1 -8 0 0 0 0 0
Alice -2 67(2) 13 -1 0 133 79(1) -1
Bob 0 0 57(5) 0 0 168 -7 0
输出范例 :
Josephus 5 376
John 4 284
Alice 4 352
Smith 3 167
Bob 2 325
Bush 0 0
#include<iostream>
#include<string>
#include<vector>
#include<set>
#include<iomanip>
using namespace std;
struct Student {
string name;
int count;
int sum;
bool operator<(const Student& other) const {
if (count != other.count) {
return count > other.count;
}
else if (sum != other.sum) {
return sum < other.sum;
}
else {
return name < other.name;
}
}
};
int main() {
int n, score;
multiset<Student> students;
cin >> n >> score;
string name;
while (cin >> name) {
int sum = 0, count = 0;
for (int i = 0;i < n;i++) {
string x;
int y;
cin >> x;
if (x.find('(') == -1) {
y = stoi(x);
if (y > 0) {
sum += y;
count++;
}
}
else {
int pos = x.find('(');
sum += stoi(x.substr(0, pos));
sum += stoi(x.substr(pos + 1, x.find(')') - pos - 1)) * score;
count++;
}
x.clear();
}
students.insert(Student{name, count, sum });
name.clear();
}
for (auto it: students) {
//cout << it.name << " \t" << it.count << " " << it.sum << endl;
cout << setiosflags(ios::left) << setw(10) << it.name << " " << resetiosflags(ios::left) << setw(2) << it.count << " " << setiosflags(ios::right) << setw(4) << it.sum << resetiosflags(ios::right)<< endl;
}
}
116 扑克牌
提示:结构体
问题描述 :
明明和他的三位同学在玩一种非常有趣的扑克牌游戏。
在这个游戏中,一副牌的大小怪被除去,然后把剩下的52张牌随机发给4个人,这样每个人的手中就有13张牌。
接下来的任务就是每个人把自己手中的牌按一定的顺序整理好。理牌的顺序如下:
首先按牌的大小整理,牌的大小顺序为:A,K,Q,J,T(10),9,…,2,如果牌的大小相等,则按如下的花色顺序整理:黑桃(S),红心(H),方块(D),草花(C)。
例如有一个人手中拿到的牌如下:
ST CQ S8 D8 HQ D2 H3 HK H9 H2 HT SK CK
经过整理后的牌的顺序会变为:
SK HK CK HQ CQ ST HT H9 S8 D8 H3 H2 D2
其中SK、HK、CK这三张牌的大小相同,都是K,于是根据花色的顺序整理,先是S,再是H,最后是C,所以顺序为SK、HK、CK。
当每个人把自己手中的牌整理完后,他们就开始玩非常有趣的扑克游戏了。但是玩着玩着,他们发现了一个问题:理牌的时间太长,这使得他们玩牌的兴致被大大减弱了。于是他们来求助于你,能否帮他们写一个理牌程序,帮助他们理牌,这样他们就可以不必把大量的时间花在理牌上面,而尽情享受玩牌的乐趣了。
明明的问题可以归结为:给你每人手中顺序打乱的13张牌,一共有4套,然后通过题目中描述的理牌顺序,理好这4套牌。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,测试数据的第一行有一个整数n,表示有几副牌需要整理,接着每副牌分四行输入,每行13张牌;每张牌用两个字母表示,首字母表示花色,尾字母表示点数,两张牌之间有一个空格。每副牌与每副牌之间没有任何空行,第一副牌前面以及最后一副牌后面也都没有任何空行。 注:通常,键盘为标准输入设备。
输出说明 :
对于每一副牌,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。对于每组输入的牌,输出排序后的牌,分四行输出,输出样式与输入相同。每组运算结果与其后一组运算结果之间有一个空行,第一组运算结果前面及最后一组运算结果后面没有空行。 注:通常,显示屏为标准输出设备。
输入范例 :
2
ST CQ S8 D8 HQ D2 H3 HK H9 H2 HT SK CK
D9 HJ H7 DJ S2 SQ DT C2 H4 H5 DA D4 D5
D6 S4 S9 S5 S7 SJ H8 D3 C8 S3 C4 S6 C9
SA C7 HA H6 DK CJ D7 CA C5 CT DQ C6 C3
D6 S4 S9 S5 S7 SJ H8 D3 C8 S3 C4 S6 C9
D9 HJ H7 DJ S2 SQ DT C2 H4 H5 DA D4 D5
ST CQ S8 D8 HQ D2 H3 HK H9 H2 HT SK CK
SA C7 HA H6 DK CJ D7 CA C5 CT DQ C6 C3
输出范例 :
SK HK CK HQ CQ ST HT H9 S8 D8 H3 H2 D2
DA SQ HJ DJ DT D9 H7 H5 D5 H4 D4 S2 C2
SJ S9 C9 H8 C8 S7 S6 D6 S5 S4 C4 S3 D3
SA HA CA DK DQ CJ CT D7 C7 H6 C6 C5 C3
SJ S9 C9 H8 C8 S7 S6 D6 S5 S4 C4 S3 D3
DA SQ HJ DJ DT D9 H7 H5 D5 H4 D4 S2 C2
SK HK CK HQ CQ ST HT H9 S8 D8 H3 H2 D2
SA HA CA DK DQ CJ CT D7 C7 H6 C6 C5 C3
#include<iostream>
#include<string>
#include<set>
using namespace std;
class Card {
public:
string id;
char number;
char flow;
int num;
int fl;
Card(string id) {
this->id = id;
number = id[1];
flow = id[0];
switch (number)
{
case 'T':
num = 10;
break;
case 'J':
num = 11;
break;
case 'Q':
num = 12;
break;
case 'K':
num = 13;
break;
case 'A':
num = 14;
break;
default:
num = number - '0';
}
switch (flow)
{
case 'S':
fl = 3;
break;
case 'H':
fl = 2;
break;
case 'D':
fl = 1;
break;
case 'C':
fl = 0;
break;
}
}
bool operator<(const Card& other)const {
if (num != other.num)return num > other.num;
else return fl > other.fl;
}
};
int main() {
int n;
cin >> n;
multiset<Card> cards;
string s;
for (int i = 0;i < n;i++) {
for (int j = 0;j < 4;j++) {
for (int z = 0;z < 13;z++) {
cin >> s;
Card c(s);
cards.insert(c);
s.clear();
}
for (auto it = cards.begin();it != cards.end();it++) {
if (it == --cards.end()) {
cout << (*it).id;
}
else cout << (*it).id << " ";
}
cards.clear();
cout << endl;
}
cout << endl;
}
}
119 挤牛奶
提示:结构体
问题描述 :
三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶。第一个农民在300时刻(从5点开始计时,秒为单位)给他的牛挤奶,一直到1000时刻。第二个农民在700时刻开始,在 1200时刻结束。第三个农民在1500时刻开始2100时刻结束。期间最长的至少有一个农民在挤奶的连续时间为900秒(从300时刻到1200时刻),而最长的无人挤奶的连续时间(从挤奶开始一直到挤奶结束)为300秒(从1200时刻到1500时刻)。 你的任务是编一个程序,读入一个有N个农民(1 <= N <= 5000)挤N头牛的工作时间列表,计算以下两点(均以秒为单位): 最长至少有一人在挤奶的时间段。 最长的无人挤奶的时间段。
输入说明 :
Line 1: 一个整数N。 Lines 2…N+1: 每行两个小于1000000的非负整数,表示一个农民的开始时刻与结束时刻。
输出说明 :
一行,两个整数,即题目所要求的两个答案,以一个空格分隔。
输入范例 :
3
300 1000
700 1200
1500 2100
输出范例 :
900 300
#include<iostream>
#include<set>
using namespace std;
struct Cow{
int start;
int end;
int during = end - start;
bool operator<(const Cow& other)const {
if (start == other.start)return start < other.start;
else return end < other.end;
}
};
int main() {
int n;
cin >> n;
multiset<Cow> cows;
for (int i = 0;i < n;i++) {
int a, b;
cin >> a >> b;
cows.insert(Cow{ a,b });
}
int maxCow = 0;
int maxNotCow = 0;
int start = 0, end = 0;
int nowDuring = 0;
for (auto it = cows.begin();it != cows.end();it++) {
if (it == cows.begin()) {
nowDuring += (*it).during;
maxNotCow = (*it).start;
//nowNotDuring += (*it).start;
start = (*it).start;
end = (*it).end;
continue;
}
if ((*it).start <= end) {
nowDuring += (*it).end - end;
}
else if ((*it).start > end) {
maxCow = maxCow > nowDuring ? maxCow : nowDuring;
nowDuring = 0;
maxNotCow = maxNotCow > ((*it).start - end) ? maxNotCow : ((*it).start - end);
}
start = (*it).start;
end = (*it).end;
}
cout << maxCow << " " << maxNotCow << endl;
}
121 分糖果
提示:一维数组
问题描述 :
肖恩和帕特里克是兄弟,他们从他们的父母那里得到了很多糖果。每一块糖具有一个正整数的价值,孩子们希望分他们得到的糖果。首先,肖恩将这些糖果分成两堆,并选择一堆给帕特里克。然后,帕特里克将尝试计算每堆的价值,其中每堆的价值是那堆糖果价值的总和,如果他觉得没有平等的价值,他将开始哭了起来。
不幸的是,帕特里克太小了,所以不能正确的计算。他只会二进制无进位的加法。比如说,他想算12(二进制为1100)加5(二进制为101),他会把最右边的两位加法算正确,但是第三位会忘记进位。(即0+0=0,0+1=1,1+0=1,1+1=0)
因此,帕特里克算12加5的结果为9。下面几个是帕特里克算的结果:
5 + 4 = 1
7 + 9 = 14
50 + 10 = 56
肖恩数学很好,他想得到价值总和更高的糖果并且不让他的弟弟哭。如果可能,他会分成两个非空的糖果袋,让帕特里克认为,双方都有相同的值的糖果。给你每一袋糖果每一块糖果的价值,我们想知道是否可能让帕特里克相信他们得到糖果价值的总量是相同的。如果可能计算出肖恩能得到的最大的价值。
输入说明 :
第一行输入T(1<T<10),表示接下来输入T组测试数据。
每组测试数据占一行,每行包含以下数据,N C1 C2 … Cn(其中N(2 ≤ N ≤ 10)代表从父母那里得到糖果的总数,C(1 ≤ Ci ≤ 100)代表每块糖果的价值)
输出说明 :
若不能输出NO,若能则输出肖恩得到的最大的价值。
输入范例 :
2
5 1 2 4 5 8
3 3 5 6
输出范例 :
NO
11
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int m;
cin >> m;
while (m--) {
int n;
int candy[100];
cin >> n;
for (int i = 0; i < n; i++) {
cin >> candy[i];
}
sort(candy, candy + n);
int realSum = 0, sum = 0;
for (int i = 0; i < n; i++) {
realSum += candy[i];
sum = sum ^ candy[i];
}
if (sum == 0) cout << realSum - candy[0] << endl;
else cout << "NO" << endl;
}
}
124 分数化小数
` 提示:字符串
问题描述 :
写一个程序,输入一个形如N/D的分数(N是分子,D是分母),输出它的小数形式。
如果小数有循环节的话,把循环节放在一对圆括号中。
例如, 1/3 = .33333333 写成0.(3)
41/333 = 0.123123123… 写成0.(123)
用xxx.0 表示整数
典型的转化例子: 1/3 = 0.(3)
22/5 = 4.4
1/7 = 0.(142857)
2/2 = 1.0
3/8 = 0.375
45/56 = 0.803(571428)
输入说明 :
单独的一行包括被空格分开的 N和D, 1 <= N,D <= 100000。
输出说明 :
小数的表示方法上面说的很明白了,如果输出的长度超过76个字符,每行输出76个字符(包括小数点、括号等)。
输入范例 :
45 56
输出范例 :`
0.803(571428)
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
bool isCircu(string s,int &pos,int &n,int cs) {
int length = s.size();
if (length < cs * 2)return false;
for (int i = cs + 1;i <= length / 2;i++) {
string behind, front;
behind = s.substr(length - i, i);
front = s.substr(length - i * 2, i);
if (behind == front&&count(behind.begin(),behind.end(),'0')!=behind.size()) {
pos = length - i * 2;
n = i;
return true;
}
}
return false;
}
int main() {
int a, b;
cin >> a >> b;
int inter = a / b;
a = a % b;
string decNum;
if (a == 0)decNum = "0";
int pos = 0, n = 0;
bool isCir=false;
while (a != 0 && isCir == false) {
a *= 10;
int x = a / b;
a = a % b;
decNum.push_back(x + '0');
isCir = isCircu(decNum,pos,n,2);
if (isCir) {
isCircu(decNum.substr(pos,n/2), pos, n, 1);
}
}
if (isCir) {
decNum.erase(pos + n);
decNum.insert(pos, 1, '(');
decNum.insert(decNum.size(), 1, ')');
}
cout << inter << "." ;
int z = 2;
for (int i = 0;i < decNum.size();i++) {
cout << decNum[i];
z++;
if (z == 76) {
cout << endl;
z = 0;
}
}
}
128 *汉诺塔问题的第m步
提示:递归
问题描述 :
给定三根杆A、B、C和大小不同的几个盘子。这些盘子按尺寸递减顺序套在A杆上,最小的在最上面。现在的任务是把这些盘子从A杆移到C杆且保持原来堆放顺序。在实现任务时,每次只能移动一个盘子,且任何时刻不允许大的盘子放在小的盘子上面,B杆可以作为辅助存放杆。求:总共有n个圆盘时,搬动过程中的第m步是从哪个杆到哪个杆。
输入说明 :
你的程序需要从标准输入设备(通常为键盘)中读入多组测试数据。每组输入数据由一行组成,每行输入一个整数表示盘子数n,1≤n≤10,以及步数m,两个数据之间以一个空格分隔。行首和行尾没有多余的空格,两组数据之间也没有多余的空行。
输出说明 :
对每组测试数据,你的程序需要向标准输出设备(通常为启动该程序的终端)依次输出一行对应的答案,该行中输出第m步移动的情况,如第m步是从A移到B,则输出“A–B”(不包括引号)。如果移动过程不存在第m步,则输出“none” (不包括引号)。
两组数据之间无空行,第一组前及最后一组后也无空行。
输入范例 :
2 3
2 4
输出范例 :
B–C
none
#include<iostream>
using namespace std;
int tap = 0;
int b = 0;
void move(char A,char B) {
tap++;
if (tap == b) {
cout << A << "--" << B << endl;
}
}
void hario(int n, char A, char B, char C) {
if (n == 1) {
move(A, C);
}
else {
hario(n - 1, A, C, B);
move(A, C);
hario(n - 1, B, A, C);
}
}
int main() {
int a;
char A = 'A', B = 'B', C = 'C';
while (cin >> a >> b) {
if (b < 0) {
cout << "none" << endl;
continue;
}
hario(a, A, B, C);
if (tap < b) {
cout << "none" << endl;
}
b = 0;
tap = 0;
}
}
10 分解质因数
提示:循环/深度优先搜索
问题描述 :
求出区间[a,b]中所有整数的质因数分解。
输入说明 :
输入两个整数a,b。
2<=a<=b<=10000
输出说明 :
每行输出一个数的分解,形如k=a1a2a3…(a1<=a2<=a3…,k也是从小到大的)(具体可看范例)
输入范例 :
3 10
输出范例 :
3=3
4=22
5=5
6=23
7=7
8=222
9=33
10=25
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> nums;
bool isP(int n) {
if (n == 2)return true;
for (int i = 2;i <= sqrt(n);i++) {
if (n % i == 0) return false;
}
return true;
}
void DFS(int n) {
if (isP(n)) {
nums.push_back(n);
return;
}
for (int i = 2;i <= sqrt(n);i++) {
if (isP(i) && n % i == 0) {
int x = n / i;
if(isP(i))nums.push_back(i);
DFS(x);
return;
}
}
}
int main() {
int n, m;
cin >> n >> m;
for (int i = n;i <= m;i++) {
DFS(i);
sort(nums.begin(), nums.end());
cout << i << "=";
for (int j = 0;j < nums.size();j++) {
if (j == nums.size() - 1)cout << nums[j];
else cout << nums[j] << "*";
}
cout << endl;
nums.clear();
}
}
13 **2n皇后问题
提示:深度优先搜索
问题描述 :
给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。
问总共有多少种放法?
n小于等于8。
说明:同一条对角线是指包括两条主对角线的所有对角线,n=5时的棋盘从左上往右下有9条对角线,从右上往左下也有9条对角线。
比如,棋盘为:
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
表示一个4*4的棋盘,所有位置都可放皇后。
则可知有2种放法。
输入说明 :
输入的第一行为一个整数n,表示棋盘的大小。
接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出说明 :
输出一个整数,表示总共有多少种放法。
输入范例 :
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
输出范例 :
0
#include<iostream>
using namespace std;
int map[10][10];
int n,types;
bool isFind(int i,int j,int t) {
if (map[i][j] != 1)return false;
for (int z = 0;z < n;z++) {
if (map[z][j] == t || map[i][z] == t) {
return false;
}
}
int line = i, po = j;
while (line < n - 1 && po < n - 1) {
line++;
po++;
if (map[line][po] == t)return false;
}
line = i, po = j;
while (line < n - 1 && po > 0) {
line++;
po--;
if (map[line][po] == t)return false;
}
line = i, po = j;
while (line > 0 && po < n - 1) {
line--;
po++;
if (map[line][po] == t)return false;
}
while (i > 0 && j > 0) {
i--;
j--;
if (map[i][j] == t)return false;
}
return true;
}
void DFS(int times,int t) {
if (times >= n && t == 2) {
DFS(0, 3);
}
else if (times >= n && t == 3) {
types++;
}
else {
for (int j = 0;j < n;j++) {
if (isFind(times, j, t)) {
map[times][j] = t;
DFS(times + 1, t);
map[times][j] = 1;
}
}
}
}
int main() {
cin >> n;
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
cin >> map[i][j];
}
}
DFS(0, 2);
cout << types;
}
14 芯片测试
提示:深度优先搜索
问题描述 :
有n(2≤n≤20)块芯片,有好有坏,已知好芯片比坏芯片多。
每个芯片都能用来测试其他芯片。用好芯片测试其他芯片时,能正确给出被测试芯片是好还是坏。而用坏芯片测试其他芯片时,会随机给出好或是坏的测试结果(即此结果与被测试芯片实际的好坏无关)。
给出所有芯片的测试结果,问哪些芯片是好芯片。
输入说明 :
输入数据第一行为一个整数n,表示芯片个数。
第二行到第n+1行为n*n的一张表,每行n个数据。表中的每个数据为0或1,在这n行中的第i行第j列(1≤i, j≤n)的数据表示用第i块芯片测试第j块芯片时得到的测试结果,1表示好,0表示坏,i=j时一律为1(并不表示该芯片对本身的测试结果。芯片不能对本身进行测试)。
输出说明 :
按从小到大的顺序输出所有好芯片的编号
输入范例 :
3
1 0 1
0 1 0
1 0 1
输出范例 :
1 3
#include<iostream>
#include<vector>
using namespace std;
int n;
int map[100][100] = { 0 };
int trueNum[100] = { 0 };
bool DFS(int line) {
for (int i = 0;i < n;i++) {
if (map[line][i] == 1&&line != i) {
trueNum[line] = 1;
if (trueNum[i] == 1) {
continue;
}
if (DFS(i) == false) {
trueNum[line] = 0;
return false;
}
}
}
return true;
}
int main() {
cin >> n;
vector<int> result;
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
cin >> map[i][j];
}
}
for (int i = 0;i < n;i++) {
trueNum[i] = 1;
if (DFS(i)) {
for (int i = 0;i < n;i++) {
if (trueNum[i] == 1) {
cout << i + 1 << " ";
}
}
break;
}
}
}
16 8皇后·改
` 提示:深度优先搜索
问题描述 :
规则同8皇后问题,但是棋盘上每格都有一个数字,要求八皇后所在格子数字之和最大。
输入说明 :
一个8*8的棋盘。
数据规模和约定
棋盘上的数字范围0~99
输出说明 :
所能得到的最大数字和
输入范例 :
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48
48 50 51 52 53 54 55 56
57 58 59 60 61 62 63 64
输出范例 :
260
#include<iostream>
using namespace std;
int map[10][10];
int n = 8,types;
int maxNum = 0;
bool isFind(int i,int j) {
for (int z = 0;z < n;z++) {
if (map[z][j] == -1 || map[i][z] == -1) {
return false;
}
}
int line = i, po = j;
while (line < n - 1 && po < n - 1) {
line++;
po++;
if (map[line][po] == -1)return false;
}
line = i, po = j;
while (line < n - 1 && po > 0) {
line++;
po--;
if (map[line][po] == -1)return false;
}
line = i, po = j;
while (line > 0 && po < n - 1) {
line--;
po++;
if (map[line][po] == -1)return false;
}
while (i > 0 && j > 0) {
i--;
j--;
if (map[i][j] == -1)return false;
}
return true;
}
void DFS(int times,int sum) {
if (times >= n) {
types++;
maxNum = maxNum > sum ? maxNum : sum;
}
else {
for (int j = 0;j < n;j++) {
if (isFind(times, j)) {
int oriNum = map[times][j];
sum += oriNum;
map[times][j] = -1;
DFS(times + 1,sum);
sum -= oriNum;
map[times][j] = oriNum;
}
}
}
}
int main() {
for (int i = 0;i < n;i++) {
for (int j = 0;j < n;j++) {
cin >> map[i][j];
}
}
DFS(0, 0);
cout << maxNum;
}
19 *排队打水问题
提示:贪心算法
问题描述 :
有n个人排队到r个水龙头去打水,他们装满水桶的时间t1、t2…………tn为整数且各不相等,应如何安排他们的打水顺序才能使他们总共花费的时间最少?
输入说明 :
第一行n,r (n<=500,r<=75)
第二行为n个人打水所用的时间Ti (Ti<=100);
输出说明 :
最少的花费时间
输入范例 :
3 2
1 2 3
输出范例 :
7
#include<iostream>
#include<algorithm>
using namespace std;
int times[501] = { 0 };
int v[501] = { 0 };
int main() {
int n, r;
cin >> n >> r;
for (int i = 0;i < n;i++) {
cin >> times[i];
}
sort(times, times + n);
int sum = 0;
for (int i = 0;i < n;i++) {
sort(v, v + r);
sum += v[0] + times[i];
v[0] += times[i];
}
cout << sum << endl;
}
26 *聪明的美食家
提示:贪心算法
问题描述 :
如果有人认为吃东西只需要嘴巴,那就错了。
都知道舌头有这么一个特性,“由简入奢易,由奢如简难”(据好事者考究,此规律也适合许多其他情况)。具体而言,如果是甜食,当你吃的食物不如前面刚吃过的东西甜,就很不爽了。
大宝是一个聪明的美食家,当然深谙此道。一次他来到某小吃一条街,准备从街的一头吃到另一头。为了吃得爽,他大费周章,得到了各种食物的“美味度”。他拒绝不爽的经历,不走回头路而且还要爽歪歪(爽的次数尽量多)。
输入说明 :
两行数据。
第一行为一个整数n,表示小吃街上小吃的数量
第二行为n个整数,分别表示n种食物的“美味度”
美味度为0到100的整数
n<1000
输出说明 :
一个整数,表示吃得爽的次数
输入范例 :
10
3 18 7 14 10 12 23 41 16 24
输出范例 :
6
#include<iostream>
#include<algorithm>
using namespace std;
int maxTimes[1000] = { 0 };
int nums[1000] = { 0 };
int n,maxi;
int main() {
cin >> n;
for (int i = 0;i < n;i++) {
cin >> nums[i];
maxTimes[i] = 1;
}
int maxNum = 1;
for (int i = 0;i < n;i++) {
for (int j = 0;j < i;j++) {
if (nums[i] >= nums[j] && nums[j]) {
maxTimes[i] = max(maxTimes[i], maxTimes[j] + 1);
}
maxNum = max(maxNum, maxTimes[i]);
}
}
cout << maxNum;
}
33 *线段和点
提示:贪心算法
问题描述 :
有n个点和m个区间,点和区间的端点全部是整数,对于点a和区间[b,c],若a>=b且a<=c,称点a满足区间[b,c]。
求最小的点的子集,使得所有区间都被满足。
输入说明 :
第一行两个整数n m
以下n行 每行一个整数,代表点的坐标
以下m行 每行两个整数,代表区间的范围
1<=n,m<=10000
0<=点和区间的坐标<=50000
输出说明 :
输出一行,最少的满足所有区间的点数,如无解输出-1。
输入范例 :
5 5
2
6
3
8
7
2 5
3 4
3 3
2 7
6 9
输出范例 :
2
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n, m;
int points[10001];
struct myNode {
int h;
int t;
}r[10001];
int isFind[10001] = { 0 };
int minNum = 9999;
bool cmp(myNode n1, myNode n2) {
if (n1.h != n2.h)return n1.h < n2.h;
else return n1.t < n2.t;
}
int main() {
cin >> n >> m;
for (int i = 0;i < n;i++) {
cin >> points[i];
}
for (int i = 0;i < m;i++) {
cin >> r[i].h;
cin >> r[i].t;
}
sort(points, points + n);
sort(r, r + m,cmp);
int start = 0,res = 0;
while (start < m) {
int temp = start;
int selectPoint = 0;
for (int i = 0;i < n;i++) {
if (points[i] == -1)continue;
for (int j = start;j < m;j++) {
if (points[i] >= r[j].h && points[i] <= r[j].t) {
if (j >= temp) {
temp = j;
selectPoint = i;
}
}
else break;
}
}
points[selectPoint] = -1;
start = temp + 1;
res++;
}
cout << res;
}
35 快速幂
提示:数学
问题描述 :
给定A, B, P,求(A^B) mod P。
输入说明 :
输入共一行。
第一行有三个数,A, B, P。
A, B为long long范围内的非负整数,P为int内的非负整数。
输出说明 :
输出共一行,表示所求。
输入范例 :
2 5 3
输出范例 :
2
#include<iostream>
#include<algorithm>
using namespace std;
int main() {
long long int a, b, p;
cin >> a >> b >> p;
long long t = 1, x = b;
a %= p;
while (x!=0) {
if (x % 2 == 1)t = a * t % p;
x /= 2;
a = a * a % p;
}
cout << t;
//cout << (long long int)(pow(a, b)) % p;
}
43 最少操作数
提示:逆向思维/深度优先搜索
问题描述 :
数组A中共有n个元素,初始全为0。你可以对数组进行两种操作:1、将数组中的一个元素加1;2、将数组中所有元素乘2。求将数组A从初始状态变为目标状态B所需要的最少操作数。
输入说明 :
第一行一个正整数n表示数组中元素的个数
第二行n个正整数表示目标状态B中的元素
n<=50,B[i]<=1000
输出说明 :
输出一行表示最少操作数
输入范例 :
2
7 8
输出范例 :
7
#include<iostream>
using namespace std;
int main() {
int n;
int nums[1001] = { 0 };
cin >> n;
for (int i = 0;i < n;i++) {
cin >> nums[i];
}
int z = 0;
bool isAllZero = false;
while (isAllZero==false) {
for (int i = 0;i < n;i++) {
if (nums[i] % 2 == 1) {
nums[i]--;
z++;
}
}
isAllZero = true;
for (int i = 0;i < n;i++) {
if (nums[i] != 0)isAllZero = false;
nums[i] /= 2;
}
z++;
}
cout << z - 1;
}
45 和最大子序列
提示:贪心算法
问题描述 :
对于一个给定的长度为N的整数序列A,它的“子序列”的定义是:A中非空的一段连续的元素(整数)。你要完成的任务是,在所有可能的子序列中,找到一个子序列,该子序列中所有元素的和是最大的(跟其他所有子序列相比)。程序要求你输出这个最大值。
输入说明 :
输入文件的第一行包含一个整数N,第二行包含N个整数,表示A。
其中
1 <= N <= 100000
-10000 <= A[i] <= 10000
输出说明 :
输出仅包含一个整数,表示你算出的答案。
输入范例 :
5
3 -2 3 -5 4
输出范例 :
4
#include<iostream>
using namespace std;
long long int n;
const long long int maxx = 1e5 + 10;
long long int num[maxx];
int main()
{
while (cin >> n) {
for (long long int i = 0; i < n; i++) {
cin >> num[i];
}
long long int max_sum = num[0], temp = num[0];
for (long long int i = 1; i < n; i++) {
temp = max(num[i], temp + num[i]);
max_sum = max(max_sum, temp);
}
cout << max_sum << endl;
}
}
小结
如上,代码有的是自己写的有的是抄的大佬的,欢迎讨论交流。
祝复试顺利!