【动态规划】爱与愁的心痛
原題傳送門
思路
本題難度本為入門難度,因為他的數據很小,用O(n2)的暴力算法就可以AC,但是,作為一個對于認為自己水題過多而感到羞愧的OIer,我決定用O(n)的算法來做這道題.
我不打算用前綴和(其實就是不會),用前綴和也可以做出O(n)的時間復雜度,但是很復雜,而且常數因子還比我接下來要介紹的算法的常數因子大,所以,我自認為我的這個算法是洛谷全站最好的(我翻了題解).
思想:貪心&動態規劃
復雜度:時間復雜度O(n);空間復雜度O(n);
如果a[n]<a[m+1],那么a[n]~a[m]區間的和一定小于a[n+1]~a[m+1]區間的和.
而a[n+1]~a[m+1]區間的和減a[n]~a[m]區間的和就等于a[m+1]-a[n].
則用dp[m+1]表示a[m+1]-a[n],那么a[n+2]~a[m+2]區間的和減a[n]~a[m]區間的和就等于a[m+1]-a[n]+a[m+2]-a[n+1]也就是b[m+1]+a[m+2]-a[n+1].而他的值又可以用dp[m+2]表示
所以得到dp[m+1]到dp[m+2]的]狀態轉移方程為:dp[m+2]=dp[m+1]+a[m+2]-a[n+1].
所以dp[m+i-1]到dp[m+i]的狀態轉移方程為dp[i+m]=dp[i+m-1]+a[i+m]-a[i]
另外,若a[1]~a[m]就是最小的范圍或者n=m,則程序會出現錯誤,需要特判:
if(dp[no]>0||n==m)//特判no=m;剩下的就很簡單了,直接上代碼.
Code
#include <iostream> #include <queue> using namespace std;long long n,m,gkmin=99999999,ans,no;//我就是喜歡把gkmin設的大一點,你咬我啊 long long a[3002]; long long dp[3002];int main() {cin>>n>>m;for(int i=1;i<=n;i++){cin>>a[i];}for(int i=1;i<=n-m;i++){dp[i+m]=dp[i+m-1]+a[i+m]-a[i];//狀態轉移if(gkmin>dp[i+m])gkmin=dp[i+m],no=i+m;}if(dp[no]>0||n==m)//特判no=m;for(int i=no;i>no-m;i--)ans+=a[i];cout<<ans;return 0; }
后記
為了裝逼敲一個高性能代碼,我足足提交了20次左右,才AC.好吧,我承認是我自己在折磨我自己QAQ.
另外,此算法仍存在改進空間,可以用遞歸的迭代法代替動態規劃的龐大dp數組,從而將空間復雜度降為O(1),但因為我懶,所以有興趣的可以自行改進.
轉載于:https://www.cnblogs.com/gongdakai/p/11031577.html
總結
以上是生活随笔為你收集整理的【动态规划】爱与愁的心痛的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BootISO:从 ISO 文件中创建一
- 下一篇: Android之获取手机上的图片和视频缩