#include <iostream>
using namespace std;
#include <cstring>
#include<algorithm>
/*老师要表扬每门课前四名 , 总分前四名 ,如果同分数情况下 ,字典序更小的先表扬
班级人数 4<=N <= 100
5
Alice 99 98 97 96
Bob 98 97 96 94
Coy 94 94 95 96
Dan 93 95 96 97
Evan 0 94 95 95
*/
struct Student_01 {
char name[105];
int score[4];
};
Student_01 stu[105];
bool cmp1_01(Student_01 a,Student_01 b) { //保证成绩相同时不会乱
if(a.score[0] != b.score[0]) {
return a.score[0] > b.score[0];
}
return strcmp(a.name,b.name) < 0;
}
bool cmp2_01(Student_01 a,Student_01 b) { //保证成绩相同时不会乱
if(a.score[1] != b.score[1]) {
return a.score[1] > b.score[1];
}
return strcmp(a.name,b.name) < 0;
}
bool cmp3_01(Student_01 a,Student_01 b) { //保证成绩相同时不会乱
if(a.score[2] != b.score[2]) {
return a.score[2] > b.score[2];
}
return strcmp(a.name,b.name) < 0;
}
bool cmp4_01(Student_01 a,Student_01 b) { //保证成绩相同时不会乱
if(a.score[3] != b.score[3]) {
return a.score[3] > b.score[3];
}
return strcmp(a.name,b.name) < 0;
}
bool cmp5_01(Student_01 a,Student_01 b) { //总分前四
int suma = 0,sumb = 0;
for(int i = 0; i < 4; i++) {
suma += a.score[i];
sumb += b.score[i];
}
if(suma != sumb) {
return suma > sumb;
}
return strcmp(a.name,b.name) < 0;
}
void print_01() {
for(int i = 0; i < 4; i++) {
printf("%s ",stu[i].name);
}
printf("\n"); //换行
}
void test_01() {
int n;
scanf("%d",&n);
for(int i = 0; i < n; i++) {
scanf("%s",stu[i].name);
for(int j = 0; j < 4 ; j++) {
scanf("%d",&stu[i].score[j]);
}
}
sort(stu,stu + n,cmp1_01);
print_01();
sort(stu,stu + n,cmp2_01);
print_01();
sort(stu,stu + n,cmp3_01);
print_01();
sort(stu,stu + n,cmp4_01);
print_01();
sort(stu,stu + n,cmp5_01);
print_01();
return;
}
/*摘气球
按跳到矮的先摘 每个小朋友都会把能够得到 气球的摘了
小朋友高度都不一样
10 10
1 2 3 4 5 6 7 8 9 10
3 1 4 6 7 8 9 9 4 12
//1.人数 气球数
//2.小朋友跳起来的高度
//3.每个气球的高度
输出 摘到气球 的数量
1
0
1
2
0
1
1
1
2
0
*/
//三个数组 ,一个标记气球是否使用 ,一个统计高度 ,一个统计答案
struct Children_02 {
int a; //够得着的 高度
int id;
};
Children_02 child[1005];
bool cmp_02_1(Children_02 a,Children_02 b) {
return a.a < b.a;
}
void test_02() { //O(n)
int h[100005]; //实际测试放全局才行AC 否则乱码 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
int ans[100005];
bool used[100005];
int n,m,p; //n 人数, m 输入气球数量 ,p 指针
scanf("%d%d",&n,&m);
for(int i = 0; i <n; i++) { //跳起来的高度
scanf("%d",&child[i].a);
child[i].id = i;
}
for(int i = 0; i < m; i++) { //气球的高度
scanf("%d",&h[i]);
}
sort(child,child + n,cmp_02_1); //按高度从小到大排
sort(h,h + m); //整理气球高度
p = 0;
for(int i = 0; i < n; i++) {
while(p < m && h[p] <= child[i].a) { //刚好指针又可以表示气球数量 ,前面拿完的气球后面拿不了
ans[child[i].id]++;
p++;
}
}
for(int i = 0; i < n; i++) {
cout<< ans[i]<<endl;
}
return;
}
/* ***快速提升代码能力
思维 转换成 计算机编程能力
常见的写法 技巧
1.代码结合 层次 缩进 快捷键 Ctrl Shift a
避免低级错误
参考文章: 程序设计竞赛中的调试技巧
*/
//放main容易爆栈 ,
/*
a + b T个数
T未给范围 ,不能开全局变量 边读入边输出
5
1 2
3 4
5 6
7 8
9 10
*/
void test_03() {
int T,a,b;
cin>>T;
for(int i = 1; i <= T ; i++) {
cin>> a >> b;
//scanf("%d%d",&a,&b);
cout<< a+b <<endl;
}
return;
}
/*斐波那契数列
f(n) = f(n - 1)+ f(n - 2);
f(n) mod 1000000007 (10^9 + 7)
*/
const int mod_04 = 1e9 + 7; //1e9 一 e 九
int f_04[100005];
void test_04() {
int n;
cin >> n;
f_04[1] = 1;
f_04[2] = 1;
for(int i = 3; i <= n; i++) {
f_04[i] = (f_04[i - 1] + f_04[i - 2]) % mod_04;
}
cout<<f_04[n] <<endl;
}
/*矩阵旋转 90°
//1.行列
//2.矩阵
3 4
-1 3 6 3
7 7 9 1
10 3 4 6
//刚好为每列逆序 后 变每行
10 7 -1
3 7 3
4 9 6
6 1 3
n行 --> i = 0 开始i列 !!!直接输出就可以 ,不用真的把原来的旋转 !
否则新建一个数组存放
*/
int num_05[205][205];
void test_05() {
int n,m;
cin>> n >> m;
for(int i = 0; i < n; i++) { //快速行列建立矩阵
for(int j = 0; j < m; j++) {
cin >> num_05[i][j];
}
}
for(int i = 0; i < m; i++) { //输出m行n列
for(int j = 0; j < n; j++) {
if(j != n - 1) //这是为了每行最后一个不要空格" " ,可能被判格式错误!!
cout <<num_05[n - j - 1][i] <<" ";
else {
cout<< num_05[n - j - 1][i] <<endl;
}
}
}
return;
}
/*求和最大的子矩阵
输入第一行n,m(1<=n,m<=50) 行 列
接下来输入矩阵
3 3
2 -4 1
-1 2 1
4 -2 2
输出
6
输出一个数 表示最大子矩阵的元素和
*/
int A_06[55][55];
void test_06() {
int n,m,ans;
cin>> n >> m ; //回车就换行 不用endl 换行
ans = -1005 ;//保证答案数值最小,也能更新ans
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
cin>>A_06[i][j];
}
}
for(int i = 0; i < n; i++) { //上 枚举上下左右边界 用 up down left right 更好
for(int j = i; j < n; j++) { //下
for(int k = 0; k < m; k++) { //左
for(int l = k; l < m; l++) { //右
int tmp = 0;
for(int p = i; p <= j; p++) { //遍历子矩阵 上到下
for(int q = k ; q <= l; q++) { // 左到右
tmp += A_06[p][q]; //累加
}
}
if(tmp > ans) {
ans = tmp; //更新
}
}
}
}
}
cout<< ans <<endl;
}
/*去重 、 排序
样例:
10
20 40 32 67 40 20 89 300 400 15
*/
#include<set>
void test_set_01() {
set<int>s1;
int n,elem;
cin >> n;
for (int i = 0; i < n ; i++) { //my利用set去重排序
scanf("%d",&elem);
s1.insert(elem);
}
cout<<s1.size()<<endl;
for (set<int>::iterator it = s1.begin(); it != s1.end(); it++)
cout << *it <<" ";
return ;
}
int num_07[105],ans[105];
void test_07() {
int n,m; //n原大小 , m记录新的大小
cin>>n;
for(int i = 0; i < n; i++) {
scanf("%d",&num_07[i]);
}
sort(num_07,num_07+n);
m= 0;
for(int i = 0; i < n; i++) {
if(i != 0 && num_07[i] != num_07[i - 1]) {
ans[m++] = num_07[i - 1];
}
}
ans[m++] = num_07[n - 1];
cout<< m << endl;
for(int i = 0; i < m; i++) {
if(i != m - 1) { //最后一个换行 且后面没有空格格式
cout<< ans[i] << " ";
} else {
cout<< ans[i] << endl;
}
}
}
/*
N,l1,r1,l2,r2
个数 区间1(从小到大) 区间2 (从大到小)
第二行 数据
输出新的 序列
样例:
6 1 3 2 4
8 3 1 6 9 2
输出
1 8 6 3 9 2
*/
int A_08[10005];
void test_08() {
int N,l1,r1,l2,r2;
cin>>N>>l1>>r1>>l2>>r2;
for(int i = 1; i <= N; i++) { //这里是从1开始填入
cin>> A_08[i] ;
}
sort(A_08+l1,A_08+r1+1);//先从小到大
sort(A_08+l2,A_08+r2+1,greater<int>()); //再从大到小
for(int i = 1; i <= N; i++) { //从1开始输出
if(i != N) {
cout<< A_08[i] <<" ";
} else {
cout<< A_08[i] <<endl;
}
}
return;
}
/*输入一个十进制数 进制 ****************** 除基取余法 N % R ,N / R;
N<= 10000 , 2<= R <= 16, 注意N可能是负数
输出R进制数
用 'A' 表示 10 , 'B' 表示 11 ...
样例:
数 进制
23 12
转换结果
18
*/
char ans_09[105];
void test_09() { //留下来对R取余的结果 ,但结果是反的,所以先存下来 ,然后倒序输出
int N,R,m,now;
cin >> N >>R;
if(N < 0) {
cout<< "-";
N = -N; //取反
}
m = 0;
while(N) {
now = N % R; //now余数
if(now <= 9) { //0 - 9
ans_09[m++] = '0' + now;
} else {
ans_09[m++] = 'A' + now - 10; //大于10 , 用 'A' 表示 10, 'B' 表示 11 ...
}
N /= R ; //除基取余法
}
if(m == 0) { //当 m等于0时打印 0
cout<< 0;
}
for(int i = m - 1; i >= 0 ; i--) {
cout<< ans_09[i] ;
}
cout<<endl;//避免多个行号
return;
}
/*任意一个正整数,如果不是回文数,将该数的 高低位 互换相加 ,若为回文数停止,计数
样例:
349
3
349--->1292--->4213--->7337
*/
int digit_10[1005];
int num_10[1005]; //如果无法判断多少空间 用 vector 等效可变数组
bool judge_10(int x) { //判断回文!!!
int cnt = 0;
while(x) {
digit_10[cnt++] = x % 10; //取每一位
x /= 10;
}
for(int i = 0; i < cnt / 2; i++) { //头尾判断 , 一半结束
if(digit_10[i] != digit_10[cnt - 1 - i]) {
return false;
}
}
return true;
}
int rev_10(int x) { //反转 !!!!!
int ret = 0;
while(x) {
ret = ret*10 + x % 10; //在个位的每次进一 ,变最高位
x /= 10;
}
return ret;
}
void test_10() {
int n , m;
cin >> n; //把每一步得到的数,变换的数存下来
m = 0;
num_10[m++] = n;
while(!judge_10(n)) { //判断回文 ,不是就反转相加 ,保存数组中
n += rev_10(n);
num_10[m++] = n;
}
cout<< m - 1 <<endl; //输出次数
for(int i = 0; i < m; i++) {
if(i != m - 1) {
cout<< num_10[i] << "--->";
} else {
cout<< num_10[i] <<endl;
}
}
return;
}
/*一个机器人礼物 4种指令
forward x 前进x米
back x 先后转 然后前进x米
left x 先左转 然后前进x米
right x 先右转 然后前进x米
输入 指令数
指令...
10
back -9
left 3
left 8
back 15
right 10
right -7
right -3
left 11
right 17
left 3
输出坐标 x y
9 -7
*/
int dx[4] = {0,-1,0,1}; //往后 往左 往右 往前初始化x轴正方向 一定要顺时针或逆时针 好对应左转或右转的变化
int dy[4] = {1,0,-1,0};
char op[15]; //存放操作指令 forward back left right
void test_11() {
int n,d,x,nowx,nowy; //n 指令数 d 当前方向 更新坐标 x,y x为命令值
cin>>n;
d = 3; //初始化当前方向x轴正方向 dx[d],dy[d] == (1,0)
nowx = 0;
nowy = 0;
for(int i = 0; i <n; i++) {
cin>>op>>x;
if(op[0] == 'b') { //因为命令的首字母不同 ,比较首字母即可
d = (d + 2) % 4; //往当前方向的反方向走
} else if(op[0] == 'l') {
d = (d + 1) %4; //向左转 打表逆时针 直接转 90° d+1
} else if(op[0] == 'r') {
d = (d + 3) %4; //向右转 == 左转 270° d+3
} //'f' 就不改变方向直接前进
nowx += dx[d] * x;//单位方向 * 命令值
nowy += dy[d] * x;
}
cout<< nowx <<" "<<nowy<<endl;
return;
}
int main() {
test_11();
return 0;
}
蓝桥杯算法入门_02 (结构体 - R进制 - 回文判断)
于 2022-03-03 10:32:02 首次发布