7

我正在尝试解决SPOJ 问题“一和零”

某些正整数的十进制表示仅由 1 和 0 组成,并且至少有一位数字 1,例如 101。如果一个正整数不具有这样的属性,可以尝试将其乘以某个正整数来确定是否产品有这个属性。

我解决这个问题的方法是简单地做 BFS。获取仅包含的字符串'1',然后对其进行 BFS,并在每个步骤中添加'1'and '0'。直到现在以字符串形式和余数跟踪数字。当余数为零时,该数被找到。

我的问题是:我的代码对于测试用例(例如 9999 或 99999)花费的时间太长。如何提高算法的运行时间?

// Shashank Jain
/*
     BFS
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <climits>
#include <string>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#define LL long long int
using namespace std;
LL n;
string ans;

void bfs()
{   
  string str,first,second;
  str+='1'; // number will start with '1' always
  if(n==1)
  {
    ans=str;
    return;
  }
  queue<pair<string,LL> >q; // pair of STRING(number) and long long int
                            // (to hold remainder till now)
  pair<string,LL>p;
  p=make_pair(str,1);
  q.push(p);
  LL rem,val,temp;
  while(q.empty()==0)
  {
    p=q.front();
    q.pop();
    str=p.first;
    val=p.second;   
    if(val==0)  // remainder is zero means this is number 
    {
      ans=str;
      return ;
    }
    // adding 1 to present number       
    temp=val*10+1; 
    rem=(temp)%n;
    firstone=str+'1';
    p=make_pair(firstone,rem);
    q.push(p);
    // adding 0 to present number       
    temp=val*10+0;
    rem=(temp)%n;
    secondone=str+'0';
    p=make_pair(secondone,rem); 
    q.push(p);  
  }
}

int main()
{
  int t,i;
  scanf("%d",&t);
  while(t--)
  {   
    scanf("%lld",&n);       
    bfs();
    for(i=0;i<ans.size();i++)
    {
      printf("%c",ans[i]);        
    }
    printf("\n");
  }
  return 0;
}
4

2 回答 2

6

我刚刚解决了这个问题。我不会发布我的代码片段,但我会指出您的代码速度较慢的原因

  1. 正如sukunrt所说,您需要保留一个大小为n的数组,您可以在其中将当前获得的模数标记为已访问,这样您就不会再次访问它,因为如果您处于已经访问过的模数,则不需要考虑到目前为止获得的字符串部分,因为它只会使数字更大(我们需要最小值),也就是说,这意味着一旦您访问一个模数,您x就会找到由 0 和 1 组成的最小数字,x当除以 n 时,该数字作为余数给出。

  2. 您总是将如此获得的字符串传递给孩子,这不仅增加了记忆力,还增加了时间。为避免这种情况,只需再取两个数组value[]parent[]大小均为 n。

    parent[i]存储模数的父模数i

    value[i]i存储与模数(0 <= i < n)对应的当前位。

    最后,您可以回溯以形成仅模数= 0的整数。

    同样在进行更改后,您的代码将给出 WA,因为您必须首先推送通过在末尾附加“0”获得的孩子,然后再推送通过在末尾附加“1”获得的孩子。(你可以自己证明)。

于 2013-06-05T19:40:23.133 回答
4

这里有一个提示。这样想:

假设您想要的数字是 X。X mod N = 0。

所以你只需要存储 N 个状态,即 0-n-1。从 1. 开始,然后做 bfs。您需要丢弃与以前具有相同余数的分支。我把证据留给你。

于 2013-06-05T18:27:32.697 回答