我正在尝试编写一个可以执行以下操作的程序:
in:
5 4
1 9 9 9 0
out:
9990
我有一个问题。它不适用于任何数字集。例如,它适用于上面的那个,但它不适用于这个:
in:
15 9
2 9 3 6 5 8 8 8 8 7 2 2 8 1 4
out: 988887814
2 9 3 6 5 8 8 8 8 7 2 2 8 1 4
我用矢量方法做了这个,它适用于任何一组数字,但我试图将它做成一个堆栈以获得更好的复杂性。
编辑----为STD :: STACK修改 使用堆栈的方法代码:
#include <iostream>
#include <fstream>
#include <stack>
using namespace std;
ifstream in("trompeta.in");
ofstream out("trompeta.out");
void reverseStack(stack<char> st) {
if(!st.empty())
{
char x = st.top();
st.pop();
reverseStack(st);
out<<x;
}
return;
}
int main()
{
int n,m,count=1;
stack <char> st;
char x;
in>>n>>m;
in>>x;
st.push(x);
for(int i=1; i<n; i++)
{
in>>x;
if(st.top()<x && count+n-i-1>=m)
{
st.pop();
st.push(x);
}
else
{
st.push(x);
count++;
if (count>m-1) break;
}
};
reverseStack(st);
}
使用向量的方法代码:
#include <iostream>
#include <fstream>
using namespace std;
ifstream in ( "trompeta.in" );
ofstream out ( "trompeta.out" );
int main ()
{
int i = 0, N, M, max, j, p = 0, var;
in >> N >> M;
char* v = new char[N];
char* a = new char[M];
in >> v;
var = M;
max = v[0];
for ( i = 0; i < M; i++ )
{
for ( j = p ; j < N-var+1; j++ )
{
if ( v[j] > max )
{
max = v[j];
p = j;
}
}
var--;
a[i] = max;
max = v[p+1];
p = p+1;
}
for ( i = 0; i < M; i++ )
out << a[i]-'0';
}
any1可以帮助我让STACK代码正常工作吗?
答案 0 :(得分:1)
使用这一事实,即最重要的数字完全胜过除了平局之外的所有其他数据,我会查看第一个(N-M + 1)个数字,找到该范围内的最大单个数字。
如果它出现一次,则锁定第一个数字。丢弃在该位置之前出现的数字,并重复“N-position的M-1个数字的最大值”以查找该数字的剩余数字。回答。 (或N位置-1,如果位置为零)
如果它多次出现,则递归地找到每个“N位置的M-1个数的最大值”,然后从这些中选择最大的单个结果。最多可以有N个这样的比赛。
我忘了提及,如果N == M,你也完成了。
递归证明: 计算子匹配的值将始终选择M-1个数字。当M为1时,您只需要选择几个位置中的最大位置,并且不再有递归。这两种情况都是如此。此外,“选择”步骤始终包含不超过N个选项,因为它们始终基于选择一个最高有效数字。
------------------你怎么用堆栈来做----------------
使用堆栈的实际实现将基于包含问题的整个状态的对象,在每个步骤中,如下所示:
struct data { // require: n == digits.size()
int n, m;
std::string digits;
bool operator<(const data &rhs){ return digits < rhs.digits; }
};
这一点不仅仅是存储原始问题,而是要有一种方法来表示任何子问题,你可以在堆栈上推送和弹出。在这里,堆栈本身并不重要,因为它用于在特定层中选择一个最佳结果。递归处理大部分工作。
这是隐藏数据结构的顶级函数:
std::string select_ordered_max(int n, int m, std::string digits) {
if (n < m || (int)digits.size() != n)
return "size wrong";
data d{ n, m, digits };
data answer = select_ordered_max(d);
return answer.digits;
}
和递归主力的粗略伪代码
data select_ordered_max(data original){
// check trivial return conditions
// determine char most_significant
// push all subproblems that satisfy most_significant
//(special case where m==1)
// pop subproblems, remembering best
return answer {original.m, original.m, std::string(1, most_significant) + best_submatch.digits };
}
当您只比较完全相同长度的字符串时,字符串比较适用于数字。这就是这种情况。
是的,我知道n和m在digits.size()中是多余的,但我不想太努力。包括它两次简化了一些递归检查。如果候选者通过该递归级别的最大数字检查,则实际实现仅将候选者推送到堆栈。这使我能够从输入的15位数中得到正确的9位数答案,只有28位候选者被推入堆栈(并且在最大选择期间弹出它们)。
答案 1 :(得分:0)
- 编辑 -
这是基于我之前使用vector
的建议的STACK建议findMaxValueOutOfNDigits(stackInput, M, N)
{
// stackInput = [2, 9, 3, 6, 5, 8, 8, 8, 8, 7, 2, 2, 8, 1, 4]
// *where 4 was the first element to be inserted and 2 was the last to be inserted
// if the sequence is inverted, you can quickly fix it by doing a "for x = 0; x < stack.length; x++ { newStack.push(stack.pop()) }"
currentMaxValue = 0
for i = 0; i < (M - N + 1); i++
{
tempValue = process(stackInput, M, N)
stackInput.pop()
if (tempValue > currentMaxValue)
currentMaxValue = tempValue
}
return currentMaxValue
}
process(stackInput, M, N)
{
tempValue = stackInput.pop() * 10^(N - 1)
*howManyItemsCanILook = (M - N + 1)
for y = (N - 2); y == 0; y++
{
currentHowManyItemsCanILook = *howManyItemsCanILook
tempValue = tempValue + getValue(stackInput, *howManyItemsCanILook) * 10^(y)
*howManyItemsCanILook = *howManyItemsCanILook - 1
for x = 0; x < (currentHowManyItemsCanILook - *howManyItemsCanILook); x++
{
stackInput.pop()
}
}
return tempValue
}
getValue(stackInput, *howManyItemsCanILook)
{
currentMaxValue = stackInput.pop()
if (currentMaxValue == 9)
return 9
else
{
goUntil = *howManyItemsCanILook
for i = 0; i < goUntil; i++
{
*howManyItemsCanILook = *howManyItemsCanILook - 1
tempValue = stackInput.pop()
if (currentMaxValue < tempValue)
{
currentMaxValue = tempValue
if (currentMaxValue == 9)
return currentMaxValue
}
}
return currentMaxValue
}
}
注意:其中* howManyItemsCanILook通过引用传递
我希望这会有所帮助
答案 2 :(得分:0)
现在你的代码有很多问题,但不是专注于那些让我们回答这个问题。假设您的代码已更正为我们提供:
const size_t M
其中M
是输出中预期的位数const vector<int> v
这是大小为N
您总是希望选择剩余最高值的最高值。因此,我们将保留一个end
迭代器,以防止我们选择一个不会给我们留下足够数字来完成数字的数字,并使用max_element
选择:
const int pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
auto maximum = 0;
auto end = prev(cend(v), M - 1);
auto it = max_element(cbegin(v), end);
for (auto i = M - 1; i > 0; --i) {
maximum += *it * pow10[i];
advance(end, 1);
it = max_element(next(it), end);
}
maximum += *it;
此代码取决于M
大于0且小于N
且小于log10(numeric_limits<int>::max())
编辑:不幸的是这解决了连续的数字问题,修改后的问题,希望以后的数字,但不一定是连续的
因此,鲜为人知的 numeric
库提供了inner_product
,这似乎只是这项工作的工具。现在你的代码有很多问题,但不是专注于那些让我们回答问题。假设您的代码已更正为我们提供:
vector<int> foo(M)
其中M
是输出中预期的位数const vector<int> v
这是大小为N
我们会在foo
中使用inner_product
,以10的递减次数初始化它:
generate(begin(foo), end(foo), [i=int{1}]() mutable {
auto result = i;
i *= 10;
return result; });
然后我们可以在循环中使用它:
auto maximum = 0;
for (auto it = prev(rend(v), size(foo) + 1); it != rbegin(v); advance(it, -1)) {
maximum = max<int>(inner_product(cbegin(foo), cend(foo), it, 0), maximum);
}
maximum = max<int>(inner_product(cbegin(foo), cend(foo), rbegin(v), 0), maximum);
要使用it
初始化,要求您的初始M
小于N
,因此您可能希望assert
或{{1}}一些东西。 击>