如果 \(dp\) 的狀態轉移方程為 \(f[i]=min\\)
那麼我們就可以考慮用 \(dij\) 的思想去優化它
因為如果某個點的 \(f\) 值是最小的,那麼就沒有其它的點可以影響它
因此我們每一次從堆中取出最小的點對其它點進行更新即可
題目描述
傳送門分析
按照期望題一般的做法,我們設 \(f[u]\) 為從 \(u\) 走到終點 \(n\) 的期望花費
設 \(du[u]\) 為節點 \(u\) 的出度
那麼 \(f[u]= \frac min(f[u],f[v])}+1\)
我們會發現這個式子既包含 \(f[u]\) 本身又包含與 \(f[u]\) 相鄰的點 \(f[v]\)
不好直接轉移
但是我們可以確定,如果 \(f[v],那麼 \(f[v]\) 一定會對 \(f[u]\) 做出貢獻
因此,我們可以利用 \(dij\) 的思想開乙個小根堆,每次取出最小的來更新其它的
因為當前的值是最小的,所以一定不會有其它的點可以影響它
我們設 \(u\) 被與它相鄰的點的 \(f\) 值更新了 \(cnt\) 次,這些值的和為 \(sum\)
則 \(f[u]=\frac+1\)
整理可得 \(f[u]=\frac\)
**
#include#include#includeconst int maxn=6e5+5;
inline int read()
while(ch>='0' && ch<='9')
return x*fh;
}int head[maxn],tot=1;
struct asdb[maxn];
void ad(int aa,int bb)
struct jie
jie(int aa,double bb)
bool operator < (const jie &a) const
};int n,m,du[maxn],cnt[maxn];
double sum[maxn],f[maxn];
bool vis[maxn];
std::priority_queueq;
void dij() }}
int main()
dij();
printf("%.10f\n",f[1]);
return 0;
}
題目描述
傳送門分析
我們設消滅第 \(i\) 個頭的代價是 \(f[i]\)
則,\(f[i]=min(f[i],a[i]+\sum f[j],b[i])\)
同樣地,我們在一開始把所有的 \(f\) 值扔進小根堆裡
每次取出隊首的元素來更新其它值
**
#include#include#include#include#include#includeconst int maxn=6e5+5;
typedef long long ll;
int head[maxn],tot=1;
struct asdb[maxn];
int n;
void ad(int aa,int bb)
struct jie
jie(int aa,ll bb)
bool operator < (const jie &a) const
};ll a[maxn],f[maxn];
int k[maxn];
bool vis[maxn];
std::priority_queueq;
void dij()
} }}int main()
} dij();
long long ans=0;
for(int i=1;i<=n;i++)
printf("%lld\n",ans);
return 0;
}
DIJ的優化,和spfa的優化
spfa和dij求最短路的演算法的坑點一直是很多的。經常會讓人搞不懂。用過載運算子來排序,如 struct cmp 這種做法是不對的,該dis值在堆裡不會更新甚至會堵住。目前只有兩種優化演算法最可靠,分別為優先佇列來優化spfa或dij。每次從堆中只需要取出到t的最短路最小的元素進行鬆弛,這樣便可以...
區間DP的主要思想
區間動態規劃問題一般都是考慮,對於每段區間,他們的最優值都是由幾段更小區間的最優值得到,是分治思想的一種應用,將乙個區間問題不斷劃分為更小的區間直至乙個元素組成的區間,列舉他們的組合 求合併後的最優值。設f i,j 1 i j n 表示區間 i,j 內的數字相加的最小代價 最小區間f i,i 0 乙...
hdu1579簡單的用dp優化遞迴
題目連線 include include include include include include const int inf 0x3f3f3f using namespace std int dp 110 n,a 110 110 sum 110 maxx int main for int i...