日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CodeForces - 372CWatching Fireworks is Fun+DP+单调队列优化

發布時間:2023/11/30 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CodeForces - 372CWatching Fireworks is Fun+DP+单调队列优化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【題目描述】
CodeForces - 372CWatching Fireworks is Fun
題目的大概意思就是在一個編號為1…n的街道上現在按照時間順序放煙花,每個煙花獲得的幸福感為b?abs(a?x)b-abs(a-x)b?abs(a?x),x為觀看煙花的位置,為了提升我們的幸福感,我們可能會移動,每個時間單位可以移動d長度,現在問我們如果可以從任何一個地點開始觀看煙花,那么最后幸福感最大是多少
【題目分析】
連我這樣不太會DP的人都能看出來這是一個DP,按照放煙花的順序dp[i][j]=max(dp[i?1][k])+b?abs(a[i]?x)dp[i][j]=max ( dp[i-1][k] )+b-abs(a[i]-x)dp[i][j]=max(dp[i?1][k])+b?abs(a[i]?x),其中k為所有可以到達j位置的點,即i?t?d&lt;=k&lt;=i+t?di-t*d&lt;=k&lt;=i+t*di?t?d<=k<=i+t?d,t是距離上次放煙花的時間差
可是這樣做的話就需要對每一個煙花都遍歷一個很大的區間,應該會超時,所以我們需要進行優化。
我們對于每個煙花,我們都 用一個隊列從前往后計算每個位置,隊列中保存的是能到達當前位置的所有區域中幸福感最大的(按照從前往后的順序),如果后面某個位置的幸福感比前面的大,就會將前面的彈出,再將后面的放進去,因為對于再往后的位置來講,后面這個幸福感更大的位置更有用(前面的能到的后面的一定能到,后面能到的前面的不一定能到,而且前面的值還沒有后面的大,所以就不用考慮他了,這也算是一種貪心吧)
可能這樣說有點繞,可以先看代碼,注意理解雙重循環的部分,再回來看就應該很好理解了。
為了優化空間,我們用一個二維的數組滾動的保存數據,s0保存的是還沒有放這個煙花的幸福感,s1保存的是放了煙花后的幸福感,對于下一個煙花,將s0和s1調換就可以了,最后s0保存的就是最后的結果,查找最大值就可以了。
【AC代碼】

#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include<cmath> #include<climits> #include<queue> #include<vector> #include<set> #include<map> using namespace std;typedef long long ll; const int MAXN=150005; ll dp[2][MAXN]; ll a,b,t,n,m,d,s0,s1,tt=1,step;int main() {scanf("%lld%lld%lld",&n,&m,&d);s0=0; s1=1;while(m--){deque<int> q;scanf("%lld%lld%lld",&a,&b,&t);step=(t-tt)*d; tt=t;for(int i=1,j=1;i<=n;i++){for(;j<=i+step&&j<=n;j++){while(!q.empty() && dp[s0][q.back()]<=dp[s0][j]) q.pop_back(); //后面的值還比前面的大,前面的就沒用了q.push_back(j); //不管有沒有前面的彈出,后面的暫時都是有用的,除非更后面的將他擠出去}while(!q.empty() && q.front()<i-step) q.pop_front(); //如果隊列剛開始的地方已經不能到達位置i,就彈出。雖然可能他的幸福感很高,但是對后面的值已經沒有影響了。dp[s1][i]=dp[s0][q.front()]+b-abs(a-i);}swap(s0,s1);}ll ans=dp[s0][1];for(int i=2;i<=n;i++){if(dp[s0][i]>ans) ans=dp[s0][i];}printf("%lld",ans);return 0; }

【參考博客】
https://www.cnblogs.com/yehs/p/11331813.html

總結

以上是生活随笔為你收集整理的CodeForces - 372CWatching Fireworks is Fun+DP+单调队列优化的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。