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

被折叠的 条评论
为什么被折叠?



