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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

小奇探险

發布時間:2023/12/3 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 小奇探险 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 題目
  • 題解
  • 代碼實現

題目

小奇去遺跡探險,遺跡里有N個寶箱,有的裝滿了珠寶,有的裝著廢品。
小奇有地圖,所以它知道每一個寶箱的價值,但是它不喜歡走回頭路,所以要按順序拿這N個寶箱中的若干個。

拿寶箱很累的。一開始小奇的體力是1 ,每得到一個寶箱之后,小奇得到的價值是體力x 寶箱的價值,之后它的體力就會變為原來的K倍 。

小奇不喜歡連續放過很多寶箱,所以任意一段長度為M的序列中,小奇一定要取走其中的一個寶箱。

現在小奇想知道它能得到的最大價值和。

輸入格式
第一行,兩個整數 N,M,表示的含義如題目中所述;
第二行,一個小數K ,表示的含義如題目中所述,最多4位小數;
第三行,N個整數,第i個整數表示第i個寶箱的價值。

輸出格式
輸出一行,一個實數,表示小奇能得到的最大價值和,四舍五入保留兩位小數。

題解

特別水也特別板的一道題。。。。
每個人都會想到三維DP
DP[i][j][k]DP[i][j][k]DP[i][j][k]:表示第i個寶箱一定選,上一次選的寶箱為j,選了k個

通過數據范圍,就已經扼殺了想開三維數組的心


那我就先舍棄k,假設沒有這個k的限制來思考一下
因為開二維都會MLE,所以就死命也要把DP壓成一維
DP[i]DP[i]DP[i]:表示第i個寶箱一定選,前面[1,i?1][1,i-1][1,i?1]不管怎么選,反正要是合法的最大價值
轉移方程式?
DP[i]=DP[j]+w[i](j∈[i?m,i?1])DP[i]=DP[j]+w[i](j∈[i-m,i-1])DP[i]=DP[j]+w[i](j[i?m,i?1])
這就是一個滑動窗口的優化(單調隊列)我要AC了!!!


但是因為有了k的限制,我們就要重新搞一下了
我們思考如果正著往后推,那么前面選了j個就會影響后面的價值
但是如果從后往前推,后面管他選了x個,對當前i的價值是沒有影響的,
當前i的價值只被前面的選取決定

所以重新定義一下DP[i]DP[i]DP[i]
表示從n往1推,第i個寶箱必須選,且[i+1,j][i+1,j][i+1,j]的選取必須是合法的最大價值
轉移方程式也就變了?
DP[i]=DP[j]+w[i](j∈[i+1,min(n+1,i+m)])DP[i]=DP[j]+w[i](j∈[i+1,min(n+1,i+m)])DP[i]=DP[j]+w[i](j[i+1,min(n+1,i+m)])


這里我只解釋兩個地方:
1:為什么要壓一個n+1??
因為數據有可能在最后的[n,n?m+1)[n,n-m+1)[n,n?m+1)全是負數,
而這個時候i距離n的距離又不到m
我就可以不選,這個時候就可以用DP[n+1]=0DP[n+1]=0DP[n+1]=0來處理

2:為什么可以取到i+m??
按我們的常規理解應該是[i+m?1,i][i+m-1,i][i+m?1,i]
仔細想想,i是一定要取的,那么[i+m?1,i][i+m-1,i][i+m?1,i]這個區間肯定是滿足m的
但是[i+m,i?1][i+m,i-1][i+m,i?1]也是可以滿足m的,所以i+m也可能對i進行貢獻

舉例說明:
m = 2,i = 1,i + m = 3
1 2 3

i
[1,2]長度是m,其中有下標為1的寶藏被拿了
[2,3]長度也是m,所以下標為3的寶藏也應該被拿

代碼實現

#include <cstdio> #include <deque> using namespace std; #define MAXN 100005 deque < int > deq; int n, m; double k, result = -0x7f7f7f7f; double w[MAXN], dp[MAXN];int main() {scanf ( "%d %d %lf", &n, &m, &k );for ( int i = 1;i <= n;i ++ )scanf ( "%lf", &w[i] );deq.push_back ( n + 1 );for ( int i = n;i >= 1;i -- ) {while ( ! deq.empty() && deq.front() > i + m )deq.pop_front();dp[i] = dp[deq.front()] * k + w[i];while ( ! deq.empty() && dp[deq.back()] <= dp[i] )deq.pop_back();deq.push_back ( i );}for ( int i = 1;i <= m;i ++ )result = max ( result, dp[i] );printf ( "%.2lf", result );return 0; }

總結

以上是生活随笔為你收集整理的小奇探险的全部內容,希望文章能夠幫你解決所遇到的問題。

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