dp转图论——cf1070A好题

Posted zsben991126

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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);
    }    
}

 

以上是关于dp转图论——cf1070A好题的主要内容,如果未能解决你的问题,请参考以下文章

CodeForces1070A Find a Number 图论

线性dp,后缀处理——cf1016C好题

[CF1070A]Find a Number_bfs

cf1272F——经典升维dp,好题!

luogu CF708C Centroids 换根dp好题

cf478d 线性dp好题