DAG之硬幣問題DP(最長路及其字典序)

2021-07-11 12:20:16 字數 1585 閱讀 6559

/*

【問題描述】

有n種硬幣,面值分別為v1,v2,v3,.....vn,每種都有無限多。

給定非負整數s,可以選用多少個硬幣,使得面值之和恰好為s?

輸出硬幣數目的最小值和最大值。1<=n>=100, 0<=s<=10000,1<=vi<=s.

【分析與思路】

思路:本題是固定終點和起點的dag動態規劃。

我們把每種面值看做乙個點,表示「還需要湊足的面值」,則初始狀態為s,目標狀態為0。

如當前在狀態i,沒使用乙個硬幣j,狀態變轉移到i-vj。

有n種硬幣,面值分別為v1,v2,v3,.....vn,每種都有無限多。

給定非負整數s,可以選用多少個硬幣,使得面值之和恰好為s?

輸出硬幣數目的最小值和最大值。1<=n>=100, 0<=s<=10000,1<=vi<=s.

本題是固定終點和起點的dag動態規劃。

我們把每種面值看做乙個點,表示「還需要湊足的面值」,則初始狀態為s,目標狀態為0。

如當前在狀態i,沒使用乙個硬幣j,狀態變轉移到i-vj。 */

遞推方法實現

#include#include#define max 10001

#define inf 1000000000;

int n, s;

int v[max] ,vis[max], d[max];

int max[max], min[max] ;

// 輸出最小字典序

void prit_ans(int *d, int s)

}// 主函式、遞推實現最短路最長路

int main ()

// 遞推演算法求解最長最短路

for (i=1; i<=s; i++)///初始化min初始化為最大值,max初始化為最小值

for (i=1; i <= s; i++)///表示的錢數

for (j=1; j<=n; j++)///對應的個數

if(i >= v[j])///當需要表示的錢幣數大於硬幣所能表示的數值時,才可以往下進行

printf("%d %d\n", min[s], max[s]);

// 輸出最優字典序

prit_ans(min, s);

printf("\n");

prit_ans(max, s) ;

printf("\n");

return 0 ;

}

記憶化搜尋方法實現。裡面加標記的地方為輸出字典序最小的序列

#include #include #include #include using namespace std;

struct data

a[1010];

int g[1010][1010];

int dp[1010];

int n;

int d(int i)

/*void print_ans(int i)}*/

int main()

}cout << maxx << endl;

//print_ans(k);

}return 0;

}

Tarjan演算法縮點 DAG最長路 DP

我們按照複雜程度來討論不同的tarjan演算法變形的差異.但此時只是有所區分的將所有的點劃分為乙個個的強連通分量,尚且沒有縮點.上面這個功能實現起來最簡單.它的tarjan函式內 的.void tarjan int u else if in stack v 還剩下一種不在棧中但是已經訪問過的情況,是...

DAG最長路(最短路)

dag就是有向無環圖。dag上的最長或者最短路是很重要的一類問題。很多問題都可以轉化為dag上的最長或者最短路徑的問題。dag求最短和最長路的方法一樣。本演算法主要解決2個問題 1 求整個dag中的最長路徑 即不固定起點,也不固定終點 2 固定終點,求dag的最長路徑。dp i 表示從i 號頂點出發...

動態規劃四(DAG最長路)

在圖的有關知識中已經了解了dag就是有向無環圖,其中計算最長路 關鍵路徑 的做法非常複雜,這裡介紹更簡單的方法。求整個dag的最長路徑 即不固定起點和終點 固定終點,求dag的最長路徑。給定乙個有向無環圖,怎樣求解整個圖的所有路徑中權值之和最大的那條。令dp i 表示從i號頂點出發能獲得的最長路徑長...