C++ 查找给定数字的可能解码数(动态规划)
我试图解决一个问题,每个字母都有各自的数字,比如a-1,b-2…z-26。 现在给出一个数字,这个数字可以用多少种方式解码是个问题。考虑一个例子,其中25114可以被解码为“bean”、“Baad”、“Yad”、“Yun”、“YKD”和“BEKD”。这可以通过6种方式进行解码。 我已经用C++编写了代码,但我得到了错误的答案。请更正我的密码C++ 查找给定数字的可能解码数(动态规划),c++,encryption,permutation,dynamic-programming,C++,Encryption,Permutation,Dynamic Programming,我试图解决一个问题,每个字母都有各自的数字,比如a-1,b-2…z-26。 现在给出一个数字,这个数字可以用多少种方式解码是个问题。考虑一个例子,其中25114可以被解码为“bean”、“Baad”、“Yad”、“Yun”、“YKD”和“BEKD”。这可以通过6种方式进行解码。 我已经用C++编写了代码,但我得到了错误的答案。请更正我的密码 #include<bits/stdc++.h> using namespace std; int total = 0; int arr[1000
#include<bits/stdc++.h>
using namespace std;
int total = 0;
int arr[100001];
void func(int start,int end,int factor){
if(start==end)
return;
int j =start;
if(factor==2&&j==end-1)//if j is the last element and factor is 2,accessing j+1 element is illegual
return;
if(factor==2){
if((arr[j]*10+arr[j+1])>26)
return;
else{
total++;
func(start+2,end,1);
func(start+2,end,2);
}
}
else{//factor is 1
total++;
func(start+1,end,1);
func(start+1,end,2);
}
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
int p;
cin>>p;
arr[i]=p;
}
func(0,n,1);
func(0,n,2);
cout<<total<<endl;
return 0;
}
从本质上说,我的代码所做的是,它从给定数组中固定一个数字,从给定数组中固定一个或两个数字,然后递归,直到覆盖所有的组合。例如,考虑到上述情况,我首先选择“2”作为我的第一个数字,并将其解码为“B”因子=1,然后选择“25”并将其解码为“E”因子=2。
**以下是以下代码的输入和输出
输入:25114
预期产出:6
我的产出:15
输入:3333 10位
预期产出:1
我的输出:10您的问题被标记为动态规划,但它绝不是。 相反,请考虑状态空间及其边界条件: 空字符串没有编码; 一个数字有一个编码;
n位字符串的编码数与n-1位子字符串的编码数相同,加上n-2位子字符串的编码数相同(如果前两位为),则您的问题被标记为动态规划,但绝对不是。 相反,请考虑状态空间及其边界条件: 空字符串没有编码; 一个数字有一个编码;
如果前两位是基于问题中的原始程序,则n位字符串的编码数与n-1位子字符串的编码数加上n-2位子字符串的编码数相等,我建议在到达末尾时仅在start==end时计算编码数 由于func总是在factor=1和factor=2的情况下被调用两次,因此我可以自由选择计算的任一条件 以下是修改后的代码:
#include<bits/stdc++.h>
using namespace std;
int total = 0;
int arr[100001];
void func(int start,int end,int factor){
if(start==end) {
if(factor == 1) total++; // count once when reaching the end
return;
}
int j =start;
if((factor==2) && (j==end-1))//if j is the last element and factor is 2,accessing j+1 element is illegal
return;
if(factor==2){
if((arr[j]*10+arr[j+1])>26)
return;
else{
//total++;
func(start+2,end,1);
func(start+2,end,2);
}
}
else{//factor is 1
//total++;
func(start+1,end,1);
func(start+1,end,2);
}
return;
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
int p;
cin>>p;
arr[i]=p;
}
func(0,n,1);
func(0,n,2);
cout<<total<<endl;
return 0;
}
还有改进的余地
我不会修改全局变量,而是从func返回组合数,并在更高级别中添加值
我还将在被调用的func中处理2位数字和1位数字之间的区别,而不是在调用方中
类似于以下伪代码:
int func(int start, int end)
{
if(remaining length is <2) {
// we reached the end, so this is one combination
return 1;
}
if(two-digit number is >26) {
// only a 1-digit number is possible, count remaining combinations
return func(start+1, end);
}
// both a 1-digit or 2-digit number is possible, add the remaining combinations for both cases
return func(start+1) + func(start+2);
}
根据问题中的原始程序,我建议在到达末尾时仅在start==end时计算编码 由于func总是在factor=1和factor=2的情况下被调用两次,因此我可以自由选择计算的任一条件 以下是修改后的代码:
#include<bits/stdc++.h>
using namespace std;
int total = 0;
int arr[100001];
void func(int start,int end,int factor){
if(start==end) {
if(factor == 1) total++; // count once when reaching the end
return;
}
int j =start;
if((factor==2) && (j==end-1))//if j is the last element and factor is 2,accessing j+1 element is illegal
return;
if(factor==2){
if((arr[j]*10+arr[j+1])>26)
return;
else{
//total++;
func(start+2,end,1);
func(start+2,end,2);
}
}
else{//factor is 1
//total++;
func(start+1,end,1);
func(start+1,end,2);
}
return;
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
int p;
cin>>p;
arr[i]=p;
}
func(0,n,1);
func(0,n,2);
cout<<total<<endl;
return 0;
}
还有改进的余地
我不会修改全局变量,而是从func返回组合数,并在更高级别中添加值
我还将在被调用的func中处理2位数字和1位数字之间的区别,而不是在调用方中
类似于以下伪代码:
int func(int start, int end)
{
if(remaining length is <2) {
// we reached the end, so this is one combination
return 1;
}
if(two-digit number is >26) {
// only a 1-digit number is possible, count remaining combinations
return func(start+1, end);
}
// both a 1-digit or 2-digit number is possible, add the remaining combinations for both cases
return func(start+1) + func(start+2);
}
对于这种算法,我希望只从main调用一个递归函数,而不是两个。没有费心去区分递归函数的代码,以准确地看到它尝试做什么和不尝试做什么,但是对递归函数的错误重复调用充分表明所提出的方法似乎存在根本性的缺陷,应该从零开始废弃和重新实现。另外,可变长度数组是非标准C++。你会从一本好的C++书籍中获益,而不是从这些谜题中得到答案。您使用的是什么输入,您实际得到的是什么输出,您想要得到什么。@Bodo对不起,我已经编辑了这篇文章,包括两个输入和输出以及预期的输出。请调查一下这个问题。感谢您提供这种算法,我希望main只调用一次递归函数,而不是两次。没有费心去区分递归函数的代码,以准确地看到它尝试做什么和不尝试做什么,但是对递归函数的错误重复调用充分表明所提出的方法似乎存在根本性的缺陷,应该从零开始废弃和重新实现。另外,可变长度数组是非标准C++。你会从一本好的C++书籍中获益,而不是从这些谜题中得到答案。您使用的是什么输入,您实际得到的是什么输出,您想要得到什么。@Bodo对不起,我已经编辑了这篇文章,包括两个输入和输出以及预期的输出。请调查一下这个问题。非常感谢。