题目: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; }
写题解为了加深记忆吧,一个题做重要的是它的思路!!!然后是优美的实现,看题解,纯属学习代码技巧,好吧。