计数类dp

https://www.acwing.com/problem/content/11/
01背包最优解计数

#include<bits/stdc++.h>
using namespace std ;

const int N = 1009 , mod = 1e9 + 7;
int dp[N] , cnt[N];//容量为j的最大价值的方案数
int n , v ;
int w[N] , val[N];

int main(){
    cin >> n >> v; 
    for(int i = 1 ; i <= n ; i++){
        cin >> w[i] >> val[i] ;
    }
    for(int i = 0 ; i <= v ; i++){
        cnt[i] = 1 ;
    }
    for(int i = 1 ; i <= n ; i++){
        for(int j = v ; j >= w[i] ; j--){
            int t = dp[j-w[i]] + val[i] ;
            if(t > dp[j]){
                dp[j] = t ;
                cnt[j] = cnt[j-w[i]];
            }else if(t == dp[j]){
                cnt[j] += cnt[j-w[i]];
                cnt[j] %= mod ;
            }
        }
    }
    cout << cnt[v] << endl;
}

该题与最短路计数思想差不多
https://www.luogu.com.cn/problem/P1608

#include<bits/stdc++.h>
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cmath>
using namespace std ;
typedef long long ll ;
const int N = 2010, M = 4000009 ;
int e[M] , ne[M] , w[M] , h[N] , idx ;
void add(int a , int b , int c){
    e[idx] = b , w[idx] = c , ne[idx] = h[a] , h[a] = idx++;
}
typedef pair<int,int> PII;
int ma[N][N];
int dis[N];
int cnt[N];
int n , m;

void dijkstra(int u){
    priority_queue<PII , vector<PII> , greater<PII>>q;
    memset(dis , 0x3f , sizeof(dis));
    dis[u] = 0 ;
    cnt[u] = 1 ;
    q.push({dis[u] , u});
    while(q.size()){
        auto x = q.top() ; q.pop() ; 
        int u = x.second , d = x.first ;
        for(int i = h[u] ; ~i ; i = ne[i]){
            int j = e[i] ;
            if(dis[j] > d + w[i]){
                dis[j] = d + w[i] ;
                cnt[j] = cnt[u] ;
                q.push({dis[j] , j});
            }else if(dis[j] == d + w[i]){
                cnt[j] += cnt[u] ;
            }
        }
    }
    if(cnt[n]){
        cout << dis[n] << " " << cnt[n] << endl;
    }else{
        puts("No answer");
    }
}



void solve(){
    memset(h , -1 , sizeof(h));
    scanf("%d%d" , &n , &m);
    for(int i = 1 ; i <= m ; i++){
        int a , b , c ;
        scanf("%d%d%d" , &a , &b , &c);
        if(ma[a][b] == 0 || ma[a][b] > c){
            add(a , b , c);
            ma[a][b] = c ;
        }
    }
    dijkstra(1);
}

signed main(){
    #ifdef ONLINE_JUDGE
	#else
		freopen("D:\\c++\\in.txt", "r", stdin);
		//freopen("D:\\c++\\out.txt", "w", stdout);
	#endif
    
        solve();
    
}
posted @ 2020-10-13 17:35  无名菜鸟1  阅读(98)  评论(0编辑  收藏  举报