dp 減少狀態 輕鬆爬山 UVA12170

2021-08-19 09:55:44 字數 1277 閱讀 6847

題意,給定n(<=70)座山的高度和d(<=1e9),每座山可以花x的代價使高度增加x或減少x,使得兩座相鄰的山高度差<=d,求最小代價,無解輸出impossible

首先大致想到,可以用f(i,k)表示已經調整完了第i座山,第i座山調整成了高度k,花費的最小代價

但是很明顯,k的範圍是1e9,顯然不通,所以就要想辦法簡化這一維

當n=3,只能調整第二座山,第二座山調整後的範圍應為(h1-d,h1+d)與(h3-d,h3+d)的交集(max(h1,h3)-d,min(h1,h3)+d),再思考一下是不是這個區間裡的數都要考慮呢?最優只有三種決策,當h2在範圍中,不調整。當h2《下界,調整至下界。當h2>上界,調整至上界。

所以推廣一下,每座山的高度就是(hi(1<=i<=n)+kd(-n雖然我也不會證明,這樣就預先n^2把這些值處理出來,拍一下序,就相當於把d離散化到n^2的數量級,dp[i][x]代表第x大的d值(記得去重,以及把負數刪掉)

在考慮轉移時,dp[i][x]就是在dp[i-1][x-d---x+d]中找乙個最小值轉移,再加上常數|h[i]-x|,這樣就可以用優先佇列來優化。看乙個dalao的**,發現其實可以不用單調佇列。借用這個思想,去重後設有m個d值,對於乙個固定的i,dp[i][1--m]是乙個單峰有最小值函式。對於乙個乙個區間內肯定單調或單峰。

優先佇列:

#include#include#include#include#define ll long long

#define inf (2100000000000000)

using namespace std;

int h[200],n,d,m;

ll a[200*400],dp[2][250*250];

struct node

node(int hei,ll v)

}q[2001010];

ll abs(ll a)

void work()

while (tail>=front&&abs(q[front].hei-a[j])>d) front++;

if (front>tail||q[front].val==inf) dp[cur][j]=inf;

else dp[cur][j]=q[front].val+abs(a[j]-h[i]);

} }for (i=1;i<=m;i++)

if (a[i]==h[n])

void work()

} for (i=1;i<=m;i++)

if (a[i]==h[n])

}int main()

UVa 10944 狀態壓縮DP

第一道狀態壓縮dp題,感覺要好好學習這種思維方式 首先設l的位置為 pointx 0 pointy 0 其他節點的位置為 pointx i pointy i 然後求出各個節點之間的距離dis i j max 我們用乙個n位2進製數 bn 1,b0 表示堅果收集情況的組合狀態 其中bi 0表示第i 1...

UVA 6625 狀態壓縮dp

這個題目的意思是給定k,n k,n 7 並給定k行每行有幾個連續的空格,所有的行左對齊,每一行最多7個,下面的行的空格數 上面相鄰行的空格數 給定乙個填數字的規則,當對於任意位置i,j num i j num i 1 j num i j num i j 1 問有 只用數字1 n 有多少種填滿空格的方...

uva11795 簡單狀態壓縮DP

一看到n 16就想到狀態壓縮dp了,而且只要儲存這個狀態就行了 轉移時也用狀態壓縮的轉移方法,比較兩個二進位制數,就能知道能否從已知狀態轉移到需要的狀態 開始沒看到題目給的就是二進位制數,自己還轉換成了二進位制 還有要記得用longlong 不能因為這個wa 還有位運算還不是很熟悉,可以用異或來去掉...