前言题
算法基础
前言
递归 和 递推 很像
递归 把问题分解为子问题 求子问题 从n到1递推 用子问题反推总问题 从1到n
题
717. 简单斐波那契
这一题 既可以用递归写,也可以用递推写
用这一题来理解递推
在递归中,求f(n) 只需递归调用f(n-1)和f(n-2)
递推写法,先算f(n-1)和f(n-2),再算f(n)
递推写法
#include#include #include #include using namespace std; int main() { int n; cin>>n; int f[46]; f[1]=0,f[2]=1; for (int i = 3; i <= n; i ++ ) f[i]=f[i-1]+f[i-2]; for (int i = 1; i <= n; i ++ ) cout< 另一个版本,速度更快
#include#include #include #include using namespace std; int n; int a,b=1,c; int main() { scanf("%d",&n); while(n--){ printf("%d ",a); c=a+b; a=b,b=c; } return 0; } 95. 费解的开关(中等)
思路
从第一行开始往下按开关,枚举第一行
每个开关只按一次
顺序不影响关键点
偏移量表示开关的变化
十进制转二进制#include#include #include #include using namespace std; const int N = 6; char g[N][N], backup[N][N]; int dx[5] = {-1, 0, 1, 0, 0}, dy[5] = {0, 1, 0, -1, 0}; void turn(int x, int y) { for (int i = 0; i < 5; i++) { int a = x + dx[i], b = y + dy[i]; if (a < 0 || a >= 5 || b < 0 || b >= 5) continue; g[a][b] ^= 1; } } int main() { int T; cin >> T; while (T -- ) { for (int i = 0; i < 5 ; i++) cin >> g[i]; int res = 10; for (int op = 0; op < 32; op++) { memcpy(backup, g, sizeof g); int step = 0; for (int i = 0; i < 5; i++) if (op >> i & 1) //将十进制转换为二进制 如果灯是灭的 { step ++ ; turn(0, i); } for (int i = 0; i < 4; i++) //处理第二行 for (int j = 0; j < 5; j++) //每一列 if (g[i][j] == '0') //如果这个灯没开 { step++; turn(i + 1,j); //下一行一定要点 } //判断最后一行 bool dark = false; for (int i = 0; i < 5; i++) if (g[4][i] == '0') { dark = true; break; } if (!dark) res = min(res, step); memcpy(g, backup, sizeof g); } if (res > 6) res = -1; cout << res << endl; } return 0; } 116. 飞行员兄弟
思路
暴力枚举 位运算#include#define x first #define y second using namespace std; typedef pair PII; const int N = 5; char g[N][N],backup[N][N]; int get(int x,int y)//返回这个位置的下标 { return 4 * x + y; } void turn_one(int x,int y)//开关翻转 { if(g[x][y]=='+') g[x][y] = '-'; else g[x][y] = '+'; } void turn_all(int x,int y) { for (int i = 0; i < 4;i++) { turn_one(x, i);//按这一列开关 turn_one(i, y);//按这一行开关 } turn_one(x, y); //因为x和y 按了偶数次 //会保持不变 再按一次 让它翻转 } int main() { for (int i = 0; i < 4; i ++) cin >> g[i]; vector res; for (int op = 0; op < 1 << 16; op++)//枚举所有的操作 1 << 16 是2的16次方 { vector temp; memcpy(backup, g, sizeof g);//备份 // *** 作 for (int i = 0; i < 4;i++)//遍历每一个位置 for (int j = 0; j < 4;j++) //如果这个开关是 1 的话 if(op >> get(i,j) & 1)//如果这个 *** 作是该位置 且是打开的 { temp.push_back({i, j});//存入数组 turn_all(i, j);// 这一行 这一列的开关都按一边 } //检查 bool closed = false; for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) { if(g[i][j]=='+') closed = true; } if(closed==false)//所有开关都是关闭的 if(res.empty() || res.size() > temp.size())//如果当前记录方案步数大于当前 *** 作步数 res = temp; memcpy(g, backup, sizeof g); } cout << res.size() << endl; for(auto op : res)//因为是从 0 开始的 cout << op.x + 1 << ' ' << op.y + 1 << endl; return 0; } 1208. 翻硬币
思路
一维的费解的开关问题,模拟一下,两个硬笔看作一个开关,每个开关只按一次#includeusing namespace std; string a, b; void turn(int x) { if(a[x] == '*') a[x] = 'o'; else a[x] = '*'; } int main() { cin >> a >> b; int res = 0; for (int i = 0; i < a.size(); i++) { if(a[i] != b[i]) { turn(i), turn(i + 1); res++; } } cout << res << endl; } 欢迎分享,转载请注明来源:内存溢出
评论列表(0条)