zoukankan      html  css  js  c++  java
  • dp转图论——cf1070A好题

    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);
        }    
    }
  • 相关阅读:
    第四次作业
    第三次作业
    作业,11
    作业,10
    作业,9
    作业,8
    作业,7
    作业,6
    作业,5
    作业,4
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10930002.html
Copyright © 2011-2022 走看看