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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

【LUOGU P1220】关路灯(区间dp)

發布時間:2025/5/22 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【LUOGU P1220】关路灯(区间dp) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一開始直接搜索+剪枝,拿了50分,發現原來是搜索搜復雜了..因為搜索是可以過的

注意到題目中有一句''再回過頭來關掉另一邊的路燈,而事實并非如此,因為在關的過程中適當地調頭有可能會更省一些",也就是說老王是在沿著某個方向走著走著突然轉向,而不是毫無邏輯的,我之前寫的搜索枚舉就是毫無邏輯的

for(int i=1;i<=n;i++){if(vis[i]) continue;vis[i]=true;dfs(...);vis[i]=false;}

而應該策略是:對于每個位置,去尋找左邊沒關掉的燈或者右邊沒有關掉的燈。之后dfs ,尋找最優情況

不過話說回來,這道題本質上是一個很好的區間DP

我們發現老王關過的燈是屬于一個區間的,而不是跳著跳著的關,因此設dp[i][j]表示老王已關閉區間[i,j]的燈,但是老王既可以在左邊也可以在右邊,所以再加一維[0/1]表示老王在左還是右

則有方程:

f[i][j][0] = min ( f[i+1][j][0] + ( a[i+1] - a[i] ) * ( sum[i] + sum[n] - sum[j] ) , f[i+1][j][1] + ( a[j]-a[i] ) * ( sum[i]+sum[n]-sum[j]) );

f[i][j][1] = min ( f[i][j-1][0] + ( a[j] - a[i] ) * ( sum[i-1] + sum[n] - sum[j-1] ) , f[i][j-1][1] + ( a[j]-a[j-1] ) * ( sum[i-1] + sum[n] - sum[j-1] ) );

其中sum是前綴和,要注意的是每次乘上的總功耗是包含了當前點i(j)的

#include<bits/stdc++.h> #define N 55 using namespace std; int n,c; int dp[N][N][2],dis[N],w[N],sum[N]; int main() {cin>>n>>c;for(int i=1;i<=n;i++){cin>>dis[i]>>w[i];sum[i]=sum[i-1]+w[i];}memset(dp,63,sizeof(dp));dp[c][c][0]=0,dp[c][c][1]=0;for(int len=2;len<=n;len++){for(int st=1;st+len-1<=n;st++){int ed=st+len-1;dp[st][ed][0]=min(dp[st+1][ed][0]+(sum[n]-sum[ed]+sum[st])*(dis[st+1]-dis[st]),dp[st+1][ed][1]+(sum[n]-sum[ed]+sum[st])*(dis[ed]-dis[st]));dp[st][ed][1]=min(dp[st][ed-1][1]+(sum[n]-sum[ed-1]+sum[st-1])*(dis[ed]-dis[ed-1]),dp[st][ed-1][0]+(sum[n]-sum[ed-1]+sum[st-1])*(dis[ed]-dis[st]));}}cout<<min(dp[1][n][0],dp[1][n][1])<<endl;return 0; }

轉載于:https://www.cnblogs.com/Patrickpwq/articles/9825484.html

總結

以上是生活随笔為你收集整理的【LUOGU P1220】关路灯(区间dp)的全部內容,希望文章能夠幫你解決所遇到的問題。

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