码迷,mamicode.com
首页 > 其他好文 > 详细

dp转图论——cf1070A好题

时间:2019-05-27 13:35:08      阅读:113      评论:0      收藏:0      [点我收藏+]

标签:图论   pair   ace   fir   中转   nbsp   color   cout   queue   

dp的状态转移很像一张有向图:每个状态为一个点,每中转移方案是一条有向边

本题要求是求出最小的数,那我们用状态[i,j]表示模i,数位和为j,那么从每个点出发的十条有向边代表[0,9]十个数

从每个状态点进行bfs,由于队首的点必定是当前最小的(因为bfs的顺序),所以可以保证最后求出的是最小的数

/*
dp[i][j]表示余数为i,和为j的状态是否被访问到 
用pre[i,j,k]表示状态[i,j]是从k转移得到的 
等效于一张有d*s个结点的图,要从(0,0)走到(0,s) ,要走最靠左边的路
 
*/
#include<bits/stdc++.h>
#include<queue>
using namespace std;
int d,s,dp[505][5005];
struct Node{
    int x,y,z;
    Node(){}
    Node(int x,int y,int z):x(x),y(y),z(z){}
}pre[505][5005];

void print(int t1,int t2){
    if(t1 || t2){
        print(pre[t1][t2].x,pre[t1][t2].y); 
        cout<<pre[t1][t2].z;
    } 
}

queue<pair<int,int> >q; 
 
int main(){
    cin>>d>>s;
        
    q.push(make_pair(0,0));
    dp[0][0]=1;
    while(!q.empty()){
        pair<int,int>p=q.front();q.pop();
        for(int i=0;i<=9;i++){
            int t1=(p.first*10+i)%d;
            int t2=(p.second+i);
            if(dp[t1][t2])continue;
            if(t2>s)break;
            q.push(make_pair(t1,t2));
            dp[t1][t2]=1;
            pre[t1][t2]=Node(p.first,p.second,i);
        }
    }
    
    if(dp[0][s]==0){
        puts("-1");
        return 0;
    }
    
    else {
        print(0,s);
    }    
}

 

dp转图论——cf1070A好题

标签:图论   pair   ace   fir   中转   nbsp   color   cout   queue   

原文地址:https://www.cnblogs.com/zsben991126/p/10930002.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!