题目:LCR 165. 解密数字
动态规划法(像这种只问你解密数字有多少种结果的,而不是让你列出每一个结果,往往可以采用动态规划)
class Solution {
public:int crackNumber(int ciphertext) {string str = to_string(ciphertext);int* f = new int[str.size()];//初试状态f【0】,f【1】的计算f[0] = 1;int temp;if (str.size() > 1) {temp = (str[0] - '0') * 10 + str[1] - '0';if (str[0] != '0' && temp <= 25)f[1] = 2;elsef[1] = 1;}//状态转移for (int i = 2; i < str.size(); i++) {temp = (str[i - 1] - '0') * 10 + str[i] - '0';if (str[i - 1] != '0' && temp <= 25)f[i] = f[i - 1] + f[i - 2];elsef[i] = f[i - 1];}return f[str.size() - 1];}
};
把每一种结果都求出来,可以使用回溯法 每次选择的列表就是stride为0或者1
要想递归代码逻辑清晰,不要乱写return
函数逻辑:翻译当前【index,index+stride】的数字,在递归调用transfer翻译后续字符——transfer(index+stride+1,path,str,0/1);
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
vector<string> finalPath;
void transfer(int index,string path,string &str,int stride) {if(index+stride>=str.size())return;//终止递归 if(stride==1) {int temp=(str[index]-'0')*10+str[index+1]-'0';if(temp<=25&&str[index]!='0') {path+=(char)(temp+'a');} else return;//剪枝 其实不算是剪枝 毕竟不符合条件的确实应该终止递归 } else {//stride==0path+=(char)(str[index]-'0'+'a');}if(index+stride==str.size()-1){finalPath.push_back(path);return;//此处完全没必要加上return;不过只是额外多调用了一次index已经越界的transfer函数,但会立即返回//所以为了逻辑清晰,不需要再加return;}transfer(index+stride+1,path,str,0);transfer(index+stride+1,path,str,1);
}
int main() {int number=216612;string str=to_string(number);string path;transfer(0,path,str,0);transfer(0,path,str,1);for(auto c:finalPath){cout<<c<<'\n';}return 0;
}