19北理&北邮
1.字符串
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e6+10;
char s[maxn];
int f[maxn];
int flag[maxn*2]; // 若flag[i] == -1表示没有f[x]+N==i的x否则使得flag[i]==x
int main(){
while(scanf("%s", s)==1) {
int N = strlen(s); // 字符串长度
int maxlen = 0; // 答案
// 思路1.暴力枚举所有子串,在满足条件的子串中寻找最长的,时间复制度为O(n^3)
// for(int i=0; i<N; i++) {
// for(int j=i; j<N; j++) {
// // 当前子串s[i,j]
// int sum = 0, len = j-i+1;
// for(int k=i; k<=j; k++) {
// sum += s[k] - '0'; // 累加数字1
// }
// if(len%2==0 && sum == len/2 && len>maxlen) { // 满足条件的子串,并且其长度比之前的都长
// maxlen = len; // 更新
// }
// }
// }
// 思路2.暴力枚举所有子串,利用相邻子串之间的关系,来得到子区间的数字和,时间复制度为O(n^2)
// for(int i=0; i<N; i++) {
// int sum = 0;
// for(int j=i; j<N; j++) {
// // 当前子串s[i,j]
// int len = j-i+1;
// sum += s[j] - '0';
// if(len%2==0 && sum == len/2 && len>maxlen) { // 满足条件的子串,并且其长度比之前的都长
// maxlen = len; // 更新
// }
// }
// }
int b[2] = {0, 0}; // b[0] 表示'0'出现的次数, b[1]表示'1'出现的次数
memset(flag, -1, sizeof(flag));
for(int i=0; i<N; i++) {
b[s[i]-'0']++; // 统计对应数字出现的次数
f[i] = b[0]-b[1]; // '0'出现的次数减去'1'出现的次数,其值在[-N, N]
if(flag[f[i]+N]==-1) { // 说明之前没有出现过这个函数值f[i]
flag[f[i]+N] = i;
} else { // 之前出现过函数值f[i], 即当前i和之前保存的那个值构成一个有效解
if(i - flag[f[i]+N] > maxlen) { // 如果这个区间更长则更新
maxlen = i - flag[f[i]+N];
}
}
}
printf("%d\n", maxlen);
}
return 0;
}
2.成绩排序
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1000+10;
struct Stu{
int score[5];
char name[20];
} ss[maxn]; // ss保存所有过线同学的信息
bool cmp(const Stu A, const Stu B) {
return A.score[4] > B.score[4]; // 根据score[4]进行降序排序
// if(A.score[4] != B.score[4]) return A.score[4] > B.score[4];
// return strcmp(A.name, B.name) < 0;
}
int main(){
int n;
scanf("%d", &n);
int line[5]; // 分数线
int cnt = 0; // 统计过线人数
for(int i=0; i<5; i++) scanf("%d", &line[i]);
for(int i=0; i<n; i++) {
int score[5];
score[4] = 0; // 总分
char name[20];
scanf("%s", name);
for(int j=0; j<4; j++) {
scanf("%d", &score[j]);
score[4] += score[j]; // 累加单科成绩
}
int ok = 1; // 标记该同学是否过线
for(int j=0; j<5; j++) {
if(score[j]<line[j]) {
ok = 0;
break;
}
}
if(ok) { // 进入复试名单,拷贝相关信息
for(int j=0; j<5; j++) ss[cnt].score[j] = score[j];
strcpy(ss[cnt].name, name);
cnt++; // 过线人数增一
}
}
sort(ss, ss+cnt, cmp); // 调用系统排序函数 ss[0, cnt)
for(int i=0; i<cnt; i++) { // 输出
printf("%s", ss[i].name);
for(int j=0; j<5; j++) printf(" %d", ss[i].score[j]);
printf("\n");
}
return 0;
}
3.反转二进制
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
int main(){
int n;
int S[40]; // 栈
int top = -1; // 栈顶指针,指向栈顶元素
while(scanf("%d", &n)==1) { // 接收多组数据,每次接收一组,处理后输出一组
top = -1; // 初始化栈
while(n>0) {
S[++top] = n%2; // 得到最低位,并放入栈中
n /= 2; // 擦除最低位,方便取高位
}
int bi = 1; // 在转换过程中乘以的数位
int sum = 0; // 转换为十进制的结果
while(top>=0) { // 栈非空
sum += S[top--] * bi; // 累加
bi *= 2;
}
printf("%d\n", sum);
}
return 0;
}
4.字母组合
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
int main(){
int n;
int S[40]; // 栈
int top = -1; // 栈顶指针,指向栈顶元素
while(scanf("%d", &n)==1) { // 接收多组数据,每次接收一组,处理后输出一组
top = -1; // 初始化栈
while(n>0) {
S[++top] = n%2; // 得到最低位,并放入栈中
n /= 2; // 擦除最低位,方便取高位
}
int bi = 1; // 在转换过程中乘以的数位
int sum = 0; // 转换为十进制的结果
while(top>=0) { // 栈非空
sum += S[top--] * bi; // 累加
bi *= 2;
}
printf("%d\n", sum);
}
return 0;
}
19中南大学
1.回文串
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 5000+10; // 问题规模
char s[maxn];
int main(){
while(scanf("%s", s) == 1) { // 接收多组数据
// 思路1.枚举所有子串,判断当前子串是否为回文串
int len = strlen(s); // 字符串长度
int ans = 0; // 统计回文串个数
// for(int i=0; i<len; i++) {
// for(int j=i; j<len; j++) {
// // 当前子串s[i, j]
// int ok = 1; // 标记当前串是否为回文串
// for(int k=0; k<=(j-i)/2; k++) {
// if(s[i+k]!=s[j-k]) { // 第k个字符和倒数第k个字符不等,当前不是回文
// ok = 0;
// break;
// }
// }
// if(ok) {
// ans++;
// }
// }
// }
// 思路2:枚举所有串的中心点,向两端展开,如果发现不是则当前中心点更长的子串不可能是回文串
for(int i=0; i<len; i++) {
int num = 0; // 向两端展开的长度,即以当前i为中心的回文串个数
while(i+num<len && i-num>=0 && s[i+num] == s[i-num]) num++; // 以i为中心的回文串个数(子串长度为奇数)
ans += num;
num = 0;
while(i+1+num<len && i-num>=0 && s[i+1+num] == s[i-num]) // // 以i和i+1为中心的回文串个数(子串长度为偶数)
ans += num;
}
printf("%d\n", ans);
}
return 0;
}
2.挖金子
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 200 + 10;
int a[maxn][maxn]; // 区域金子量
int b[maxn]; // 考虑某一行,b[i]表示[0, i]这个区域中并且选择了i个金子能得到最大值
// b[i] = max(b[i-2], b[i-3])+a[i]
int c[maxn]; // c[i]表示第i行能得到的最多金子数量
int d[maxn]; // d[i]表示考虑[0,i]行,选择了第i行能得到最多金子
int main(){
int n, m;
while(scanf("%d%d", &n, &m)==2) {
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) scanf("%d", &a[i][j]);
}
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
b[j] = max(j-2>=0?b[j-2]:0, j-3>=0?b[j-3]:0) + a[i][j];
}
c[i] = max(b[m-1], m-2>=0?b[m-2]:0); // 第i行能得到的最多金子数量
d[i] = max(i-2>=0?d[i-2]:0, i-3>=0?d[i-3]:0) + c[i];
}
printf("%d\n", max(d[n-1], n-2>=0?d[n-2]:0));
}
return 0;
}
3.合并排序
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 100 + 10;
int a[maxn], b[maxn], c[maxn];
int main(){
int n, m;
while(scanf("%d", &n)==1) {
for(int i=0; i<n; i++) scanf("%d", &a[i]);
scanf("%d", &m);
for(int i=0; i<m; i++) scanf("%d", &b[i]);
int p=0, q=0, k=0; // 分别扫描线性表a和b
while(p<n || q<m) { // 两个表中还有数据
if(q>=m || p<n&&a[p]<=b[q]) c[k++] = a[p++]; // 将a表当前数据放入c表
else c[k++] = b[q++]; // 将b表当前数据放入c表
}
for(int i=0; i<k-1; i++) { // 输出前面k-1个数据
printf("%d ", c[i]);
}
printf("%d\n", c[k-1]); // 输出最后一个数据
}
return 0;
}
4.走路还是坐公交
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
int Q[maxn]; // Q表示队列
int front=0, rear=0; // 队头和队尾指针
int vis[maxn]; // 标记访问数组, vis[i]==0表示i结点没有访问
int d[maxn]; // d[i]表示i结点层次(距离s的最短路径)
int fa[maxn]; // fa[i]==j表示i的父节点是j
int main(){
int s, e;
while(scanf("%d%d", &s, &e)==2) {
front = 0, rear = 0; // 初始化栈
memset(vis, 0, sizeof(vis)); // 初始化vis数组表示每个结点都没有访问
memset(d, 0, sizeof(d));
Q[rear++] = s; // 将初试结点加入队列
vis[s] = 1;
while(front<rear) { // 队列非空进行BFS搜索
int u = Q[front++]; // 出队
if(u==e) { // 找到了
printf("%d\n", d[u]);
while(u!=s) {
printf("%d ", u);
u = fa[u];
}
break;
}
// 分别判断三个邻居结点是否访问,如果没有访问加入队尾,并标记访问,更新层次信息
if(u*2<maxn && !vis[u*2]) {
Q[rear++] = u*2;
d[u*2] = d[u] + 1;
vis[u*2] = 1;
fa[u*2] = u;
}
if(u+1<maxn && !vis[u+1]) {
Q[rear++] = u+1;
d[u+1] = d[u] + 1;
vis[u+1] = 1;
fa[u+1] = u;
}
if(u-1>=0 && !vis[u-1]) {
Q[rear++] = u-1;
d[u-1] = d[u] + 1;
vis[u-1] = 1;
fa[u-1] = u;
}
}
}
return 0;
}