递归 和 递推 很像
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<<f[i]<<" ";
return 0;
}
另一个版本,速度更快
#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<int, int> 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<PII> res;
for (int op = 0; op < 1 << 16; op++)//枚举所有的操作 1 << 16 是2的16次方
{
vector<PII> 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. 翻硬币
#include
using 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;
}