P1037 [NOIP2002 普及组] 产生数 (dfs+高精度)

题目:P1037 [NOIP2002 普及组] 产生数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

最近感觉搜索一直掌握得不太好,就做做bdfs,今天上午做了这道题,学到了一些东西。dfs+高精度

#include<bits/stdc++.h>
using namespace std;
int k;
string s;

multimap<char,char>mp;
set<string>S;

void dfs(int n){
   if(n>k) return;

      int len=s.length();
     for(int i=0;i<len;i++){
         for(auto x:mp){
             if((i!=len-1 && s[i]==x.first && s[i+1]!='0') ||(i==len-1 && s[i]==x.first)){
                   s[i]=x.second;
                   S.insert(s);
                   dfs(n+1);
                   s[i]=x.first;
             }
         }
     }
}

int main()
{
      cin>>s>>k;
       for(int i=0;i<k;i++){
           char a,b;
           cin>>a>>b;
           mp.insert({a,b});
       }

        S.insert(s);
        dfs(0);
         cout<<S.size();
    return 0;
}

 最开始是直接两层for直接暴力搜索,没有好好了解题意,其实数字的每一位单独考虑,求方案数,然后所有的位置的方案数直接相乘就是答案。但是n的数据范围是10^30,long long也得见祖宗好吧,得使用高精度,学了下高精度,用一个数组存下答案,最后除去所有的前导0,就可以输出结果了。

 写的过程中有一个细节,怎么判断mp中是否有st的键值?如果有怎么遍历对应键值的vector<int>。

正确题解:

#include<bits/stdc++.h>
#define int long long
using namespace std;

string s;
int k,ans;
map<int,vector<int>>mp;
int vis[10];
int hm[31];

void hpm(int num){
     int t=0;
    for(int i=1;i<=30;i++){
        hm[i]=hm[i]*num+t;
         t=hm[i]/10;
         hm[i]%=10;
    }
}

void dfs(int st){
   if(vis[st]) return;
     vis[st]=1;
        ans++;
      if(mp.find(st)!=mp.end()){
          for(auto x:mp[st]){
              dfs(x);
          }
      }
}

signed main()
{
    cin>>s>>k;
     for(int i=0;i<k;i++){
         int a,b;
          cin>>a>>b;
          mp[a].push_back(b);
     }

     int len=s.length();
        hm[1]=1;
      for(int i=0;i<len;i++){//s的每一个位置
            ans=0;
          memset(vis,0,sizeof(vis));
          dfs(s[i]-'0');
           //cout<<ans<<endl;

            //高精度乘法
             hpm(ans);
      }

       int p=30;
       while(!hm[p] && p>1) p--;
        for(int i=p;i>=1;i--) cout<<hm[i];
    return 0;
}

写题解为了加深记忆吧,一个题做重要的是它的思路!!!然后是优美的实现,看题解,纯属学习代码技巧,好吧。 

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值