本blog对笔者遇到的相关问题和代码进行总结。本期是第一期:基础算法类
Ⅰ、矩阵操作类
1.回形遍历
//回形遍历
#include<iostream>
#include<cmath>
#include<memory.h>
#include<algorithm>
int a[20][20];
using namespace std;
int ans[500];
int num = 0;
void print() {
for (int i = 0; i < num - 1; i++) {
cout << ans[i] << ' ';
}
cout << ans[num - 1] << endl;
}
int main(){
int n, m;
cin >> n >> m;
int nn = n; int mm = m;
int sum = n * m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> a[i][j];
}
}
int i = 0; int j = 0;
while (sum) {
for (; i < nn; i++) {
ans[num] = a[i][j]; num++;
sum--;
if (sum == 0) {
print(); return 0;
}
}
i--;
j++;
for (; j < mm; j++) {
ans[num] = a[i][j]; num++;
sum--;
if (sum == 0) {
print(); return 0;
}
}
j--;
i--;
for (; i >= n - nn; i--) {//这里要取等
ans[num] = a[i][j]; num++;
sum--;
if (sum == 0) {
print(); return 0;
}
}
i++;
j--;
for (; j > m - mm; j--) {//因为回到了边界所以不能取等
ans[num] = a[i][j]; num++;
sum--;
if (sum == 0) {
print(); return 0;
}
}
i++;
j++;
mm--;
nn--;
}
return 0;
}
2.环形矩形输出(上例的变形)
//环形矩形输出
#include<iostream>
using namespace std;
int ans[10][10];
void print(int a) {//打印a*a方阵
for (int i = 0; i < a; i++) {
for (int j = 0; j < a; j++) {
cout << ans[i][j] << ' ';
}
cout << endl;
}
}
int main() {
int n;
cin >> n;
int row = n; int col = n;
int sum = n * n;
int i = 0; int j = 0;
int num = 1;
while (sum) {
for (; j < col; j++) {//right
ans[i][j] = num++;
sum--;
if (sum == 0) {
print(n);
return 0;
}
}
i++;
j--;
for (; i < row; i++) {//down
ans[i][j] = num++;
sum--;
if (sum == 0) {
print(n);
return 0;
}
}
j--;
i--;
for (; j >= n - col; j--) {//left
ans[i][j] = num++;
sum--;
if (sum == 0) {
print(n);
return 0;
}
}
j++;
i--;
for (; i > n - row; i--) {
ans[i][j] = num++;
sum--;
if (sum == 0) {
print(n);
return 0;
}
}
i++;
j++;
row--;
col--;
}return 0;
}
3.对角遍历
//对角线遍历矩阵
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 100;
int matrix[maxn][maxn];
int n, m;
void print() {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
cout << matrix[i][j] << ' ';
}
cout << endl;
}
}
int main() {
cin >> m >> n;
//m*n
int count = m + n - 1;//对角线遍历次数
int row=0; int col=0;
int num = 0;
for (int i = 0; i < count; i++) {//发现对角线的数字规律是关键@!
if (i % 2 == 0) {
//向右上遍历
while (row >= 0 && col < n) {
matrix[row][col] = num;
num++;
row--; col++;
}
if (col < n) {
row++;
}
else { row += 2; col -= 1; }
}
else {
while (col >= 0 && row < m) {
matrix[row][col] = num;
num++;
col--; row++;
}
if (row < m) {
col++;
}
else { col += 2; row--; }
}
}
print();
}
4.对角遍历变式
//对角遍历变形:顺便练习了递归,也没那么难hh
#include<iostream>
#include<cmath>
#include<math.h>
int matrix[4][4] = {
{0,2,5,9},
{1,4,8,12},
{3,7,11,14},
{6,10,13,15}
};//看好题目嗷
int ans;
void F(int x, int y, int n) {
if (n <= 0)return;
int temp = pow(4, n - 1);
int a = 0; int b = 0;
for (; a < 4; a++) {
if (x >= a * temp&&x < (a + 1)*temp) {
break;
}
}/
for (; b < 4; b++) {
if (y >= b * temp&&y < (b + 1)*temp) {
break;
}
}//在(a,b)大子块内
ans += matrix[a][b] * temp*temp;
x = x - a * temp;
y = y - b * temp;//在新的小矩形内重复上述判断
F(x, y, n - 1);
return;
}
using namespace std;
int main() {
int n, x, y; ans = 0;
while (cin >> n >> x >> y) {
if (n == 0)return 0;
ans = 0;
F(x, y, n);
cout << ans << endl;
}
return 0;
}
二、字符串操作类
1.大整数乘法
//大整数乘法
#include<iostream>
#include<string>
const int maxn = 10010;
int res[maxn];
using namespace std;
int main() {//统计上小数位就能改成小数乘法
string s1, s2;
cin >> s1 >> s2;
int l1 = s1.length();
int l2 = s2.length();
for (int i = 0; i < l1; i++) {
for (int j = 0; j < l2; j++) {
res[i + j] = (s1[i] - '0')*(s2[j] - '0');
}
}
if (res[0] >= 10)cout << res[0] / 10;
for (int i = l1 + l2 - 1; i > 0; i--) {
if (res[i] >= 10) {
res[i - 1] += res[i] / 10;
res[i] %= 10;
}
}
for (int i = 0; i < l1 + l2 - 1; i++) {
cout << res[i];
}
return 0;
}
2.大整数加法
//大整数加法
#include<iostream>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<memory.h>
const int maxn = 100;
using namespace std;
int main() {
int n;
cin >> n;
while(n--){
string s1, s2;
int k;
cin >> k >> s1 >> s2;
int num1[maxn], num2[maxn];
memset(num1, 0, sizeof(num1));
memset(num2, 0, sizeof(num2));//这样就不用讨论了
int l1 = s1.length();
int l2 = s2.length();
num1[0] = s1[0] - 48;//直接赋值相当于赋值ascii码
num2[0] = s2[0] - 48;
for (int i = 1; i < l1 - 1; i++) {
num1[i] = s1[i + 1] - 48;
}
for (int i = 1; i < l2 - 1; i++) {
num2[i] = s2[i + 1] - 48;
}
for (int i = max(l1, l2) - 2; i >= 1; i--) {
num2[i] = num1[i] + num2[i];//统一存在num2里
if (num2[i] >= k) {
num2[i] -= k;
num2[i - 1] += 1;
}
}
cout << num2[0] << '.';
int length = max(l1, l2);
while (num2[length - 1] == 0) { length--; }
if (length == 0)continue;
for (int i = 1; i < length; i++) {
cout << num2[i];
}
cout << endl;
}
return 0;
}
3.拨钟问题
//拨钟问题
#include<iostream>
using namespace std;
int main() {
int z[10];
int i[10];
for (int i = 1; i <= 9; i++) {
cin >> z[i];
}
int sum = 0;
int ans[20];
int num = 0;
for ( i[1] = 0; i[1] < 4; i[1]++) {
for (i[2] = 0; i[2] < 4; i[2]++) {
for (i[3] = 0; i[3] < 4; i[3]++) {
for (i[4] = 0; i[4] < 4; i[4]++) {
for (i[5] = 0; i[5] < 4; i[5]++) {
for (i[6] = 0; i[6] < 4; i[6]++ ) {//每个操作执行的次数
for (i[7] = 0; i[7] < 4; i[7]++) {
for (i[8] = 0; i[8] < 4; i[8]++) {
for (i[9] = 0; i[9] < 4; i[9]++) {
sum = 0;//每次操作前都归0
sum += (z[1] + i[1] + i[2] + i[4]) % 4;
sum += (z[2] + i[1] + i[2] + i[3] + i[5]) % 4;
sum += (z[3] + i[2] + i[3] + i[6]) % 4;
sum += (z[4] + i[1] + i[4] + i[5] + i[7]) % 4;
sum += (z[5] + i[1] + i[3] + i[5] + i[7] + i[9]) % 4;
sum += (z[6] + i[3] + i[5] + i[6] + i[9]) % 4;
sum += (z[7] + i[4] + i[7] + i[8]) % 4;
sum += (z[8] + i[5] + i[7] + i[8]+i[9]) % 4;
sum += (z[9] + i[6] + i[8] + i[9]) % 4;
//怎么确定是最小?循环次数最小?
if (sum == 0) {
for (int j = 1; j <= 9; j++) {
while (i[j]--)
ans[num++]= j;
}
for (int i = 0; i < num - 1; i++) {
cout << ans[i] << ' ';
}cout << ans[num - 1] << endl;
return 0;
}
}
}
}
}
}
}
}
}
}
}
4.两个日期之间的天数
//日期之间的距离
#include<iostream>
using namespace std;
bool R(int i) {
return i % 4 == 0 && i % 100 != 0 || i % 400 == 0;//闰年返回1
}
struct P {
int y;
int m;
int d;
};
int main() {
int year[2] = { 365,366 };
int day[2][12] = { {31,28,31,30,31,30,31,31,30,31,30,31},{31,29,31,30,31,30,31,31,30,31,30,31} };
P start, end;
cin >> start.y >> start.m >> start.d;
cin >> end.y >> end.m >> end.d;
int ans = 0;
for (int i = start.y; i < end.y; i++) {
int temp = R(i);
ans += year[temp];//先算上一共隔着多少年
}
//算下初始的距离1.1多少天
int ans1 = 0; int temp1 = R(start.y);
for (int i = 0; i < start.m-1;i++) {
ans1 += day[temp1][i];
}
ans1 += start.d;
int ans2 = 0; int temp2 = R(end.y);
for (int i = 0; i < end.m - 1; i++) {
ans2 += day[temp2][i];
}
ans2 += end.d;
int ret = ans - ans1 + ans2;
cout << ret << endl;; return 0;
}
三、补充类
//setw控制输出间隔
//setfill控制输出填空;在iomanip里
#include<iomanip>
#include<iostream>
using namespace std;
int main() {
cout << setfill('x')<<setw(5) << 1 << endl;//setw和setfill位置可以互换。但是二者和被输出内容的前后不同输出样貌不同
//除了setfill外一定要有额外的输出,这样才能输出
cout << 1 << setw(5) << setfill('5') << endl;//这样就填不上了
}