CodeForces - 1070A Find a Number (最小字典序最短路)

题意:找出能被d整除且数位和为s的最小值。(d<=500,s<=5000)

设状态(S,M)表示数位和为S,对d取模为M的数,则题目等价于求从(0,0)转移到(s,0)的最小字典序最短路。

因为每个结点所连的所有边权都是唯一的,所以直接从起点bfs即可。(如果边权不唯一,需要把边权相同的作为整体处理)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=5010+10,inf=0x3f3f3f3f;
 5 int vis[N][510],d,s;
 6 struct D {int S,M;} fa[N][510];
 7 queue<D> q;
 8 void upd(D u,D f) {if(!vis[u.S][u.M])vis[u.S][u.M]=1,fa[u.S][u.M]=f,q.push(u);}
 9 bool bfs() {
10     while(q.size())q.pop();
11     memset(vis,0,sizeof vis);
12     upd({0,0}, {-1,-1});
13     while(q.size()) {
14         D u=q.front();
15         q.pop();
16         if(u.S==s&&u.M==0)return 1;
17         for(int k=u.S==0?1:0; k<=9&&u.S+k<=s; ++k)upd({u.S+k,(u.M*10+k)%d},u);
18     }
19     return 0;
20 }
21 void dfs(D u) {
22     if(u.S==0)return;
23     dfs(fa[u.S][u.M]),printf("%d",u.S-fa[u.S][u.M].S);
24 }
25 int main() {
26     scanf("%d%d",&d,&s);
27     if(!bfs())puts("-1");
28     else dfs({s,0}),puts("");
29     return 0;
30 }

 

posted @ 2020-03-15 15:06  jrltx  阅读(194)  评论(0编辑  收藏  举报