基础算法之模拟
2026/9/3 6:56:12 网站建设 项目流程

模拟

就是把题目意思转化为代码,即自然语言翻译为编程语言

1,链接

https://www.luogu.com.cn/problem/P1067

2,题目

3,解析

模拟+分类讨论

tip:一定要好好读题,其实思路就是题目

4,代码

#include<iostream> #include<cmath> using namespace std; int main(){ int n;cin >> n; //按指数递减 for(int i = n;i>=0;i--){ int num; cin >> num; //先去不要的 if(num == 0) continue; //符号 //首位->+不管,-要加 if(i == n && num < 0) cout << "-"; //其他->+-,0没有 else if(i != n){ if(num > 0) cout << "+"; else cout << "-"; } //数字 int cnt = abs(num); if(cnt != 1 || i == 0) cout << cnt; //未知量 if(i == 1) cout << "x"; else if(i != 0 ) cout << "x^" << i; } return 0; }

P5731 【深基5.习6】蛇形方阵

1,链接

https://www.luogu.com.cn/problem/P5731

2,题目

3,解析

way1:遍历

我们可以发现规律,旋转具有周期性,所以直接4循环,用left bottom left right来不断缩边界

way2:方向向量(矩阵题通法)(其实我更喜欢叫坐标法)

通用步骤:

1,定义

dx[],dy[] ->

(0,1)上 (0,-1)下 (1,0)左, (-1,0)右

2,规则

step1:

沿一个方向走

ddl:越界

step2:

用方向向量

求:下一个方向+正确位置

循环

ddl:完成

4,代码

way1: 遍历

#include<iostream> using namespace std; int a[10][10]; int main(){ int n; cin >> n; int top = 1,bottom = n,left = 1,right = n; int num = 1; while(num <= n*n){ for(int i = left;i <=right && num <= n*n;i++) a[top][i] = num++;top++; for(int i = top;i <=bottom && num <= n*n;i++) a[i][right] = num++; right--; for(int i = right;i >=left && num <= n*n ;i--) a[bottom][i] = num++;bottom--; for(int i = bottom;i >= top && num <= n*n;i--) a[i][left] = num++;left++; } for(int i = 1;i <= n;i++){ for(int j = 1;j <= n;j++){ printf("%3d",a[i][j]); } cout << endl; } return 0; }

way2:方向向量(矩阵题通法)(其实我更喜欢叫坐标法)

错误示例:

下一位的位置没有确定

#include<iostream> using namespace std; int a[10][10];//地图 //按变化顺序定义:右,下,左,上 int dx[]={0,1,0,-1}; int dy[]={1,0,-1,0}; int main(){ int n; cin >> n; int x = 1,y =1;//当前z坐标 int cnt = 1;//当前的数 int pos = 1;//当前数到下一数方向(右,下,左,上) while(cnt <= n * n){ //存当前位置 a[x][y] = cnt; //解决越界 if(x+1 <1 || x+1 > n || y+1 < 1 || y+1 > n || a[x+1][y+1]){ pos = (pos+1)%4; } //检验完毕,赋值 x = x+dx[pos],y = y+dy[pos]; cnt++; } for(int i = 1;i <= n;i++){ for(int j = 1;j<= n;j++){ cout << a[i][j] << " "; } cout << endl; } return 0; }

正确代码

#include<iostream> using namespace std; int a[10][10];//地图 //按变化顺序定义:右,下,左,上 int dx[]={0,1,0,-1}; int dy[]={1,0,-1,0}; int main(){ int n; cin >> n; int x = 1,y =1;//当前z坐标 int cnt = 1;//当前的数 int pos = 0;//当前数到下一数方向(右,下,左,上) while(cnt <= n * n){ //存当前位置 a[x][y] = cnt; //判断下一位 //先试验 int xx = x + dx[pos]; int yy = y + dy[pos]; //解决越界 if(xx <1 || xx > n || yy < 1 || yy > n || a[xx][yy]){ pos = (pos+1)%4; xx = x + dx[pos],yy= y + dy[pos]; } //检验完毕,赋值 x = xx,y = yy; cnt++; } for(int i = 1;i <= n;i++){ for(int j = 1;j<= n;j++){ printf("%3d",a[i][j]); } cout << endl; } return 0; }

为什么越界有a[xx][yy]?

举 n=3 的例子: 当程序走到数字9,坐标x=2,y=2,此时方向 pos=2(向左)。

  • 算预测:xx=2, yy=1
  • xx,yy没有越界,但是a[2][1]=8,已经填过数字!
  • 如果不判断a[xx][yy],程序还会往左走,就会覆盖已经写好的8,矩阵直接错乱。

全局数组初始全部是 0。a[xx][yy]为真 = 这个位置≠0 = 已经填过数,要转弯。

P1098 [NOIP 2007 提高组] 字符串展开

1,链接

https://www.luogu.com.cn/problem/P1098

2,题目

3,解析

按题意直接写

4,代码

错误代码

这是我自己写的代码

#include<iostream> #include<cctype> #include<algorithm> using namespace std; int main(){ int p1,p2,p3; cin >> p1 >> p2 >> p3; string s; cin >> s; int l = 0; for(int i = 1;i < (int)s.size()-1;i++){ if(s[i] == '-'){ if((s[i-1]>='a'&&s[i+1]<='z'&&s[i+1]>s[i-1])||(s[i-1]>='0' && s[i+1]<='9'&&s[i+1]>s[i-1])){ for(int j = l;j<= i-1;j++) cout << s[j]; l = i+1; string a = ""; if(p1 == 1){ char m = s[i-1]+1; while(m < s[i+1]){ for(int k= 1;k<= p2;k++){ a += m; } m += 1; } } else if(p1 == 2){ char m = toupper(s[i-1]+1); while(m < toupper(s[i+1])){ for(int k = 1;k <= p2;k++){ a += m; } m += 1; } } else if(p1 == 3){ char m = s[i-1]+1; while(m < s[i+1]){ for(int k = 1;k <= p2;k++){ a += "*"; m++; } } } if(p3 == 2) reverse(a.begin(),a.end()); cout << a ; } } } for(int i = l;i <s.size();i++) cout << s[i]; return 0; }

大家知道错在哪吗

->因为数字可能是两位甚至更多

修改

加上字符串拼接

#include <iostream> #include <string> #include <cctype> #include <algorithm> using namespace std; int main() { int p1, p2, p3; cin >> p1 >> p2 >> p3; string s; cin >> s; int l = 0; for (int i = 1; i < (int)s.size() - 1; i++) { if (s[i] == '-') { if ((s[i - 1] >= 'a' && s[i + 1] <= 'z' && s[i + 1] > s[i - 1]) || (s[i - 1] >= '0' && s[i + 1] <= '9' && s[i + 1] > s[i - 1])) { for (int j = l; j <= i - 1; j++) { cout << s[j]; } l = i + 1; string a = ""; if (p1 == 1) { char m = s[i - 1] + 1; while (m < s[i + 1]) { for (int k = 1; k <= p2; k++) { a += m; } m += 1; } } else if (p1 == 2) { char m = toupper(s[i - 1] + 1); while (m < toupper(s[i + 1])) { for (int k = 1; k <= p2; k++) { a += m; } m += 1; } } else if (p1 == 3) { char m = s[i - 1] + 1; while (m < s[i + 1]) { for (int k = 1; k <= p2; k++) { a += '*'; } m++; } } if (p3 == 2) reverse(a.begin(), a.end()); cout << a; } } } for (int i = l; i < (int)s.size(); i++) cout << s[i]; return 0; }

正常写法

存字符串里

#include <iostream> #include <algorithm> #include <string> using namespace std; int p1, p2, p3, n; string s; string ret; bool isdig(char ch) { return ch >= '0' && ch <= '9'; } bool islet(char ch) { return ch >= 'a' && ch <= 'z'; } void add(char left, char right) { string t; for(char ch = left + 1; ch < right; ch++) { char tmp = ch; if(p1 == 2 && islet(tmp)) tmp -= 32; else if(p1 == 3) tmp = '*'; for(int i = 0; i < p2; i++) { t += tmp; } } if(p3 == 2) reverse(t.begin(), t.end()); ret += t; } int main() { cin >> p1 >> p2 >> p3 >> s; n = (int)s.size(); for(int i = 0; i < n; i++) { char ch = s[i]; if(s[i] != '-') { ret += ch; } else { if(i == 0 || i == n - 1) { ret += ch; } else { char left = s[i-1]; char right = s[i+1]; if( (isdig(left) && isdig(right) && right > left) || (islet(left) && islet(right) && right > left) ) { add(left, right); } else { ret += ch; } } } } cout << ret << endl; return 0; }

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询