由于为了双创学分,报了学校的一个c语言竞赛实训,虽然大一的时候也学过一点算法(但是后来怕秃头就没学了)。没办法啊,又得重新开始学,然后就做起了老师布置的杭电oj的4道题。分别是1040,1045,1872,2020。这几题的思路其实都很简单,只是我太菜了而已。(代码都是cpp文件)

1、1040
这题就是个简单的冒泡排序,只不过是需要一点点加工而已。根据题目描述,我们是需要先输入测试的组数n,然后再输入n行数据,每一行的第一个数是这一行需要排序的数量(大概就这么个意思吧)。

解题思路:先定义一个n来输入测试组数,然后再定义一个一维数组,数组的大小就是n,即每行测试数据的数量。再定义一个二维数组,来存储n行的所有需要排序的数据。然后就直接冒泡排序就行了。有个需要注意的小问题就是,在输出数组的时候,两个数之间要有空格,但是数组末尾不能有空格,不然无法AC的,oj的题好像都是这样。

代码

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
49
50
#include<iostream>
using namespace std;

/**
*冒泡对一个数组排序 ,升序
*参数:传入的数组,数组的大小n
*/
void Asc(int a[],int n){
int i,j,temp;
for(i = 0;i < n;i ++){
for(j = 1;j < n - i;j++){
if(a[j - 1] > a[j]){
temp = a[j - 1];
a[j - 1] = a[j];
a[j] = temp;
}
}
}
}

int main() {
int n,i,j;
int a[10]; //每组数据大小
int b[10][200]; //存放所有要排序的数据

cin >> n; //输入测试样例组数

/*输入测试数据*/
for(i = 0;i < n;i++){
cin >> a[i];
for(j = 0;j<a[i];j++){
cin >> b[i][j];
}
}

/*排序,再输出*/
for(i = 0;i<n;i++) {
Asc(b[i],a[i]);
for(j = 0;j<a[i];j++){
/*对空格进行简单的处理*/
if(j == a[i] - 1){
cout << b[i][j];
}else{
cout << b[i][j] << " ";
}
}
cout << "\n";
}
return 0;
}

2、1045
这题是个简单的DFS应用,碉堡的上下左右四个方向都可以发射炮弹,条件是设置的碉堡不能打到其他的碉堡(可以打到墙)。该题的目的是要输入一个城市地图,然后求得可以设置的最大碉堡数。

解题思路:用dfs进行深度优先遍历,从坐标0,0开始遍历,每一个坐标,都要遍历在其上下左右四个方向的其他坐标的内容,判断是否是一个碉堡,如果是个碉堡,返回false。如果是墙,则忽略。如果既不是墙,又满足以上条件,则把该坐标设置为碉堡,计数变量加一,继续递归调用dfs函数。调用后再回退一步,变量也要改回去。直到所有的点都被访问。(用了一个max函数来求两个函数的最大值,还有一个memset函数用来初始化数组,所以要加入对应的库)

代码

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<memory.h>
using namespace std;
#define size 4 //大小最大为4

/*以下:W代表墙,D代表碉堡*/
char world[size][size]; //城市地图
int n;
int Count; //用于计数
int Max = 0; //记录最大值

/*判断当前位置是否可以放置碉堡*/
bool judge(int x,int y) {
/*往上寻找*/
for(int i = x - 1;i >= 0;i--){
if(world[i][y] == 'D')
return false;
if(world[i][y] == 'X')
break;
}
/*往左寻找*/
for(int i = y - 1;i >= 0;i--){
if(world[x][i] == 'D')
return false;
if(world[x][i] == 'X')
break;
}
/*往下寻找*/
for(int i = x + 1;i < 4;i++){
if(world[i][y] == 'D')
return false;
if(world[i][y] == 'X')
break;
}
/*往右寻找*/
for(int i = y + 1;i < 4;i++){
if(world[x][i] == 'D')
return false;
if(world[x][i] == 'X')
break;
}
return true;
}

/*Dfs深度遍历*/
void dfs(){
Max = max(Count,Max); //记录最大值

/*枚举所有情况,取最大值*/
for(int i = 0;i<n;i++) {
for(int j = 0;j<n;j++){
if(world[i][j] == '.' && judge(i,j)){
world[i][j] = 'D'; //符合条件,放入碉堡
Count ++;
dfs();
/*回溯后,放回原值*/
world[i][j] = '.';
Count --;
}
}
}
}

int main(){
while(1){
cin >> n;
/*如果n为0,则结束循环*/
if(n == 0){
break;
}

Count = 0;
Max = 0;
memset(world,0,sizeof(world)); //用memset进行数组的初始化
for(int i = 0;i<n;i++){
getchar(); //读取换行符,因为是char型数组
for(int j = 0;j< n;j++){
cin >> world[i][j];
}
}
dfs();
cout << Max << "\n";
}
return 0;
}

3、1872
这题考的是稳定排序,其实也蛮简单的,但是我因为太不细心了,一直AC不了。(最后还是成功了)具体题意就是,先输入一个数代表有几行数据,然后紧跟着输入这一组数据,每行数据是名字和分数(未排序的)。然后再输入这组数据根据某种算法的排序结果。后面的就不说了。

解题思路:把每行数据用一个结构体表示,结构体内容为名字,分数,还有一个就是该行数据的位置或者序号(应该是一个意思吧)。输入结构体的时候,这个位置的值就等于用于for循环的迭代器的值,具体看代码。然后将这组数据用sort函数排序,排序依据是:降序、数据相等时,位置小的在前。然后就可以判断已经排序好的那组数据,先立两个flag为true。如果在相同的位置,两组数据对应的分数不相同,这明显就是排序错误嘛,立个flag1为false,如果分数相同,位置对应不上,那就是不稳定排序啦。(这个题目描述好像有解释的)。再立flag2为false呗。如果经过上面两个判断,两个flag都还是true的话,那就是正确的稳定排序啦。

代码

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
using namespace std;
#define Max 311

/*定义一个结构体存储*/
struct node{
int score;
char name[60];
int pos; //当前元素的位置
}stu[Max];

/*返回sort排序的条件*/
bool cmp(node a,node b){
if(a.score != b.score){
return a.score > b.score;
}
else{
return a.pos < b.pos;
}
}

int main() {
int N;
char reName[311][60];
int reScore[311];

while(scanf("%d",&N) != EOF){
/*待排序数据*/
for(int i = 0;i<N;i++){
cin >> stu[i].name >> stu[i].score;
stu[i].pos = i;
}
/*已排序数据*/
for(int i = 0;i<N;i++) {
cin >> reName[i] >> reScore[i];
}

/*稳定排序*/
sort(stu,stu+N,cmp);

int flag1 = 1;
int flag2 = 1;

/*判断是错误排序还是不稳定排序*/
for(int i = 0;i<N;i++){
if(stu[i].score != reScore[i]) flag1 = 0;
if(strcmp(stu[i].name,reName[i]) != 0) flag2 = 0;
}

/*输出错误排序结果,已经是否是稳定排序,不稳定排序也输出稳定排序结果*/
if(!flag1){
cout << "Error" << "\n";
for(int i = 0;i<N;i++){
cout << stu[i].name << " " << stu[i].score << "\n";
}
}
else if(!flag2){
cout << "Not Stable" << "\n";
for(int i = 0;i<N;i++){
cout << stu[i].name << " " << stu[i].score << "\n";
}
}
else if(flag1 && flag2){
cout << "Right" << "\n";
}
}
return 0;
}

4、2020
这题好简单,也没啥好记录的了。就是个加了绝对值运算的冒泡排序。
直接上代码吧:

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
49
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
#define N 100

int a[N];

/**
*冒泡对一个数组排序 ,降序,用绝对值进行比较
*/
void Desc(int a[],int n){
int i,j,temp;
for(i = 0;i < n;i ++){
for(j = 1;j < n - i;j++){
if(abs(a[j - 1]) < abs(a[j])){
temp = a[j - 1];
a[j - 1] = a[j];
a[j] = temp;
}
}
}
}

int main(){
int n;
cin >> n;
while(n != 0){
/*输入数据*/
for(int i = 0;i<n;i++){
cin >> a[i];
}

Desc(a,n); //降序绝对值排序

/*输出*/
for(int i = 0;i<n;i++){
if(i == n-1){
cout << a[i];
}
else{
cout << a[i] << " ";
}
}
cout << "\n";
cin >> n;
}
return 0;
}