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 }