-
7-1 对称排序 (25 分)
你供职于由一群丑星作为台柱子的信天翁马戏团。你刚完成了一个程序编写,它按明星们姓名字符串的长度非降序(即当前姓名的长度至少与前一个姓名长度一样)顺序输出他们的名单。然而,你的老板不喜欢这种输出格式,提议输出的首、尾名字长度较短,而中间部分长度稍长,显得有对称性。老板说的具体办法是对已按长度排好序的名单逐对处理,将前者放于当前序列的首部,后者放在尾部。如输入样例中的第一个案例,Bo和Pat是首对名字,Jean和Kevin是第二对,余此类推。
输入格式:
输入包含若干个测试案例。每个案例的第一行含一个整数n(n>=1),表示名字串个数。接下来n行每行为一个名字串,这些串是按长度排列的。名字串中不包含空格,每个串至少包含一个字符。n=0为输入结束的标志。
输出格式:
对每一个测试案例,先输出一行“Set n”,其中n从1开始取值,表示案例序号。接着是n行名字输出,如输出样例所示。
输入样例:
7
Bo
Pat
Jean
Kevin
Claude
William
Marybeth
6
Jim
Ben
Zoe
Joey
Frederick
Annabelle
5
John
Bill
Fran
Stan
Cece
0
输出样例:
SET 1
Bo
Jean
Claude
Marybeth
William
Kevin
Pat
SET 2
Jim
Zoe
Frederick
Annabelle
Joey
Ben
SET 3
John
Fran
Cece
Stan
Bill
#include<iostream>
#include<cstring>
using namespace std;
int main(){
int n;
int w=0;
while(1){
cin>>n;
if(n==0) break;
string s[n],e[n];
for(int i=0;i<n;i++) cin>>s[i];
for(int i=0,j=n-1,k=0;i<n;j--,k++){
e[k]=s[i];
//cout<<e[k]<<endl;
i=i+1;
if(i>=n) break;
e[j]=s[i];
i=i+1;
}
w++;
printf("SET %d\n",w);
for(int i=0;i<n;i++){
cout<<e[i]<<endl;
}
}
}
#include<iostream>
#include<cstring>
using namespace std;
int main(){
int n;
int w=0;
while(1){
cin>>n;
if(n==0) break;
string s[n];
for(int i=0;i<n;i++) cin>>s[i];
w++;
printf("SET %d\n",w);
for(int i=0;i<n;i++){
if(i%2==0)
cout<<s[i]<<endl;
}
for(int i=n-1;i>=0;i--){
if(i%2==1)
cout<<s[i]<<endl;
}
}
}
-
7-2 字符串输入练习 (I) (15 分)
计算字符串的长度。
输入格式:
每行一个字符串。
输出格式:
针对每行字符串,输出该串的长度。
输入样例:
hello world!
welcome to acm world
输出样例:
在这里给出相应的输出。例如:
12
20
理解错了题目,以为是循环读入字符串,一直从键盘读入,最后Ctrl+Z停止输入:
C语言
#include<stdio.h>
#include<cstring>
int main(){
char s[100];
while(gets(s)){
printf("%d\n",strlen(s));
}
}
然而gets在C11标准中已被正式删除,编译不通过。
cin读入遇空格就结束输入。
变量为string类型,不是字符数组,考虑getline()函数
#include<iostream>
#include<cstring>
using namespace std;
int main(){
string a;
while(getline(cin,a)){
cout<<a.size()<<endl;
}
}
还可以考虑cin.get(char *str,int maxnum) 和 cin.getline(char *str,int maxnum) 可接收空格,遇回车结束输入。
int main()
{
char st[50];
cin.getline(a,50);
//cin.get(a,50);
cout<<a<<endl;
}
-
7-3 20052 字符串排序 (15 分)
从键盘输入10个字符串,从小到大排序并输出。
输入格式:
10个字符串。
输出格式:
排序后的10个字符串。
输入样例:
apple
pear
people
hello
is
are
Disk Operating System
dis
notebook
Hi Li
输出样例:
在这里给出相应的输出。例如:
Disk Operating System
Hi Li
apple
are
dis
hello
is
notebook
pear
people
又把题目看错了,不是比较字符串的长度,而是大小
#include<algorithm>
using namespace std;
struct P{
string c;
int num;
}T[10];
bool compare(P a,P b){
return a.num>b.num;
}
int main(){
for(int i=0;i<10;i++){
getline(cin,T[i].c);
T[i].num=T[i].c.size();
}
sort(T,T+10,compare);
for(int i=0;i<10;i++)
cout<<T[i].c<<endl;
}
修改后的AC代码:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
string T[10];
bool compare(string a,string b){
if(a<b) return true;
else return false;
}
int main(){
for(int i=0;i<10;i++){
getline(cin,T[i]);
}
sort(T,T+10,compare);
for(int i=0;i<10;i++)
cout<<T[i]<<endl;
}
C++添加的string字符串是一个类,该类对运算符>、<和==进行了重载,能够直接比较两个字符串的大小。
C语言中的字符串常用strcmp比较大小。
-
7-4 30057 判断一个字符串是否是另一个字符串的子串 (15 分)
判断一个字符串是否是另一个字符串的子串。如字符串s1=”onetwothreeforth”,字符串s2=”for”,即s2是s1的子串,程序输出”YES!”,否则输出”NO!”。假如strlen(s1)>= strlen(s2)。
输入格式:
输入两个字符串。
输出格式:
s2是s1的子串,程序输出“YES!”,否则输出"NO!”。
输入样例:
onetwothreeforth
for
输出样例:
YES!
输入样例:
onetwothreeforth
the
输出样例:
NO!
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main(){
char a[10000],b[10000];
cin.get(a,10000);
getchar();
cin.get(b,10000);
int j=0;int flag=1;
for(int i=0;i<strlen(a);i++){
if(a[i]==b[j]){
j++;
if(j==strlen(b)) {
flag=0;
break;
}
}
else j=0;
}
if(flag) printf("NO!");
else printf("YES!");
}
才开始用cin.get() 发现需要在中间加getchar()
-
7-6 值班安排 (50 分)
医院有A、B、C、D、E、F、G 7位大夫,在一星期内(星期一至星期天)每人要轮流值班一天,如果已知: (1)A大夫比C大夫晚1天值班; (2)D大夫比E大夫晚1天值班; (3)E大夫比B大夫早2天值班 (4)B大夫比G大夫早4天值班; (5)F大夫比B大夫晚1天值班; (6)F大夫比C大夫早1天值班; (7)F大夫星期四值班。 就可以确定周一至周日的值班人员分别为:E、D、B、F、C、A、G。 编写程序,根据输入的条件,输出星期一至星期天的值班人员。
输入格式:
先输入一个整数n,再输入n组条件,要求能够根据输入的条件确定唯一的值班表,且输入的n组条件中能够直接或间接得到任意两位大夫的关联关系,例如上面的条件(2)直接显示了D与E间的关系,而通过条件(1)、(6)、(5)可以间接得到A与B的关系。 条件的输入格式有2种: 格式1:编号 比较运算符 编号 天数 其中比较运算符有2种:> 或 < ,分别表示“早”或“晚” 例如:A<C1 表示:A大夫比C大夫晚1天值班 格式2:编号 = 数值 例如:F=4 表示:F大夫在星期四值班
输出格式:
输出周一至周日的值班序列。
输入样例:
7
A<C1
D<E1
E>B2
B>G4
F<B1
F>C1
F=4
输出样例:
EDBFCAG
以前写过一次,又重新写了一次,主要的算法相同,但是存储结构不同,第一次存储的是所有输入的字符串,第二次全部转化成二维数组,类似于图;
第二次AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char t[7][7];
int vist[7];
struct point{ //结构体,方便排序
char str;
int week;
}w[7];
int N;
void dfs(int x){
vist[x]=1;
for(int i=0;i<N;i++){
if(vist[i]==1) continue;
if(t[x][i]){
w[i].str=i+'A';
w[i].week=w[x].week+t[x][i];
dfs(i);
}
}
}
bool compare(point a,point b){
return a.week<b.week;
}
int main(){
cin>>N;int begin;
for(int i=0;i<N;i++){
char s[5];
scanf("%s",s);
if(s[1]=='=') {
begin=s[0]-'A'; //!!
w[s[0]-'A'].str=s[0];
w[s[0]-'A'].week=s[2]-'0';
}
else{
if(s[1]=='<'){
t[s[0]-'A'][s[2]-'A']=s[3]-'0';
t[s[2]-'A'][s[0]-'A']=-(s[3]-'0');
}
else{
t[s[0]-'A'][s[2]-'A']=-(s[3]-'0'); //忘记-‘0’了
t[s[2]-'A'][s[0]-'A']=s[3]-'0';
}
}
}
dfs(begin);
sort(w,w+7,compare);
for(int i=6;i>=0;i--) printf("%c",w[i].str);
}
第一次AC代码:第一次写得很辛苦,字符和int不断的转换,很容易错漏:
//不想再看第二遍的代码
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
char mess[9][5];
int N;
char a[8];
int vist[9];
void print(){
for(int j=1;j<8;j++){
printf("%c",a[j]);
}
printf("\n");
}
void dfs(char x,int y){
for(int i=0;i<N;i++){
if(vist[i]==-1) continue;
if(mess[i][0]==x){
if(mess[i][1]=='<'){
int q=mess[i][3]-'0';
a[y-(mess[i][3]-'0')]=mess[i][2];
//vist[y+(mess[i][3]-'0')]=-1;
//vist 的参数 不能与a相同
vist[i]=-1; //两次遍历到了同一行字符
dfs(mess[i][2],y-(mess[i][3]-'0'));
}
else if(mess[i][1]=='>'){
a[y+(mess[i][3]-'0')]=mess[i][2];
vist[i]=-1;
dfs(mess[i][2],y+(mess[i][3]-'0'));
}
}
if(mess[i][2]==x){
if(mess[i][1]=='<'){
a[y+(mess[i][3]-'0')]=mess[i][0];
vist[i]=-1;
dfs(mess[i][0],y+(mess[i][3]-'0'));
}
else{
a[y-(mess[i][3]-'0')]=mess[i][0];
vist[i]=-1;
dfs(mess[i][0],y-(mess[i][3]-'0'));
}
}
}
}
int main(){
cin>>N;
int mark=-1;
for(int i=0;i<N;i++){
scanf("%s",mess[i]);
if(mess[i][1]=='=') mark=i;
}
a[mess[mark][2]-'0']=mess[mark][0];//错误a[mess[mark][2]] 字符转int一定要-‘0’
char q1=mess[mark][0];
vist[mark]=-1;
dfs(q1,mess[mark][2]-'0');
print();
return 0;
}
/*
1.问题:
mess[4][0]==q1 mess[5][0]==q1 正向循环为什么先循环了5
if(mess[4][0]==q1) printf("1!!!!!!!");
解决:
Vist数组 中的i 不是 字符串的i 主函数vist参数错了,应该等同于字符串的行数
每次vist 都忽略了4
*/
-
7-7 二维数组每列排序 (10 分)
一个4×5的整型二维数组,从键盘输入数据,并对该数组的每一列按从小到大的顺序排列后输出。
输入格式:
输入4行5列的矩阵,每行第一个数前没有空格,每行的每个数之间各有一个空格。
输出格式:
输出4行5列的矩阵,每行第一个数前没有空格,每个数输出占4列列宽。
输入样例:
5 1 1 4 2
1 2 3 4 5
8 4 5 2 1
7 5 3 6 4
输出样例:
1 1 1 2 1
5 2 3 4 2
7 4 3 4 4
8 5 5 6 5
这是一道和字符串没有关系的二维数组的题目
就是发现加了空格反而没办法AC,所以注释掉了
列出一部分具体的点来看希望转化成的数组是什么样子的,不容易出错
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main(){
int s[5][4];
for(int i=0;i<4;i++){
for(int j=0;j<5;j++)
scanf("%d",&s[j][i]);
}
/*显示转换后的矩阵
for(int i=0;i<5;i++){
for(int j=0;j<4;j++){
printf("%d ",s[i][j]);
}
printf("\n");
}
*/
for(int i=0;i<5;i++)
sort(s[i],s[i]+4);
for(int i=0;i<4;i++){
for(int j=0;j<5;j++){
//if(j!=0) printf(" ");
printf("%4d",s[j][i]);
}
printf("\n");
}
}
%4d 列宽为4 (要输出%d
只需在前面再加上一个%
,要输出\
只需在前面再加上一个\
,要输出双引号也只需在前面加上一个\
即可)