我需要一个用c ++编写的程序:
LOOP:
如果该数字是偶数除以2(n = n / 2) 如果它甚至不能执行以下操作之一: n + 1个 n-1个
LOOP ENDS
程序应该这样做直到n = 1。 但它应该以最有效和最快的方式做到这一点,我唯一的提示是我可以使用DP方法。 输出应该是用于计算该数字的操作数。 例如:
15-> 16-> 8-> 4-> 2-> 1输出:5
35-> 36-> 18-> 9-> 8-> 4-> 2-> 1输出:7这里是我编写的代码,但它还没有完成,这是错误的,因为我无法弄清楚我应该如何在每一步中添加或减去:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int n;
int h=0;
int i=0;
cout<<"Enter A Number:";
cin >> n;
int r=n;
int q=n;
cout<<r;
L1: while ( r % 2 == 0)
{
for(int m=0;r>1 && m==0 ;)
{ r=r / 2;h++;
m=r%2;
cout<<" => "<<r;
}}
while(r%2==1 && r>1)
{r=r-1;cout<<" => "<<r;h++;
goto L1;}
cout<<endl;
//**********************
cout<<q;
L2: while ( q % 2 == 0)
{
for(int m=0;q>1 && m==0 ;)
{ q=q / 2;i++;
m=q%2;
cout<<" => "<<q;
}}
while(q%2==1 && q>1)
{q=q+1;cout<<" => "<<q;i++;
goto L2;}
cout<<endl<<"First:"<<h<<endl<<"Second:"<<i<<endl;
system("pause");
}
答案 0 :(得分:2)
如果您想要使用DP解决它:
我会说:对于每个可能的值1&lt; = i&lt; N找到最佳步数。 我们使用优先级队列来执行此操作,我们在每次迭代中提取最高数字。这比长度为N的向量更有效,因为很多状态是不可达的(例如,在15例中i = 10)。
考虑起始状态是(15,0):15,零移动。 从这里你创建了两个新状态(8,2)和(7,2)因为每个你需要两个步骤(加/减+除法)。
提取(8,2):( 7,2)(4,3)
提取(7,2):( 4,3)(3,4)DP来了! (7,2)会创建状态(4,4)但你只在队列中保留相同状态的最小步数。
提取(4,3):( 2,4)(3,4)
提取(3,4):( 2,4)(1,6)
提取(2,4):( 1,5)
这就是解决方案的5个步骤。
35的步骤:
(35,0)---&gt;(18,2)(17,2)-----&gt; (17,2)(9,3)-----&gt;
(9,3)(8,4)----&gt; (8,4)(5,5)(4,5)----&gt; (5,5)(4,5)-----&gt;
(4,5)(3,7)(2,7)----&GT; (3,7)(2,6)-----&gt; (2,6)(1,9)----&gt; (1,7)
解决方案:7个步骤。
答案 1 :(得分:0)
看看这对你有帮助。
// Example program
#include <iostream>
#include <string>
int f (int n)
{
int iterations = 0;
while (n > 1)
{
if (n % 2 != 0)
{
std::cout << n << "->";
++n;
if (n & (n - 1))
n -= 2;
++iterations;
}
std::cout << n << "->";
n >>= 1;
++iterations;
}
std::cout << n << "->";
return iterations;
}
int main()
{
std::cout << f(15) << std::endl;
std::cout << f(41) << std::endl;
std::cout << f(43) << std::endl;
}
答案 2 :(得分:0)
对于动态编程的使用,你应该进行递归以获得问题的子解决方案,然后自己解决问题。您还必须使用内存结构来保存此类子解决方案的结果。
#include <deque>
#include <iostream>
using namespace std;
int solve(deque<int>& solution, int number) {
if(number >= solution.size()) // resize to fit
solution.resize(number + 1, -1);
if(number == 1) // special case for number 1
return solution[number] = 0;
if(solution[number] != -1) // if already calculated
return solution[number];
if(number % 2 == 0) // n=n/2
return solution[number] = solve(solution, number/2) + 1;
int solutionA = solve(solution, number + 1); // n++
int solutionB = solve(solution, number - 1); // n--
return solution[number] = std::min(solutionA, solutionB) + 1; // best of n++,n--
}
int main() {
deque<int> solution;
cout << solve(solution, 35);
}
我不确定代码是否可行。
答案 3 :(得分:0)
这是我的递归解决方案,针对DP示例验证了高达2097152。
它的基础是使用最后两位的值来确定最佳操作。如果最后一位是0
,我们总是分开。如果最后两位是11
,我们总是递增,因为这转换为100
,这启用了两个连续的除法运算。
如果最后两位是01
,我们递减,因为这给我们的下一个操作两个连续的除法运算与递增,这给了我们10
。
角落的情况是数字3,其中3 - >在推广到4时需要2。
我怀疑你可以通过扫描位模式来进一步优化它,以确定所需的操作数量。即每个零需要一个div运算,并且一组1可以通过一次加法变为零。
#include <cstdint>
int solve_algorithmically(std::uint64_t number)
{
// If 1 there is nothing to do.
if (number <= 1)
return 0;
// Nasty hack to get around the case where number=3 & 3 == 3 will cause increment
if (number == 3)
return solve_algorithmically(number - 1) + 1;
// If we have an even number (0 in LSB)
if ((number & 1) == 0)
return solve_algorithmically(number / 2) + 1;
// If we have two consecutive 1's i.e. (...11) then increment as this wil give us two zeroes.
// The exception is the root case 3 where decrement wins.
if ((number & 3) == 3)
return solve_algorithmically(number + 1) + 1;
// The only other case ends last two bits = 01
return solve_algorithmically(number - 1) + 1;
}
int main() {
for (auto i = 1; i < 2097152; i++)
{
int alg = solve_algorithmically(i);
}
}