題意:給3個數x, k, t。經一系列操作後,使x變為1,求最少的操作次數。具體操作為:每次x可以減去乙個數0~t,或者除以k。
解析:本題使用dp,但是需要用單調佇列進行優化。
動規需要從1開始,一直往上計算,直到x為止。
遞迴公式為:dp[i]=min(min(dp[i-t]~dp[i-1])+1,dp[i/k]+1)
單調佇列:單調佇列中的數字都是遞增或者遞減的。本題中佇列用來儲存下標,隊首的下標總是對應i-1~i-t中次數最小的那個數的下標。
單調佇列是指:佇列中元素之間的關係具有單調性,而且,隊首和隊尾都可以進行出隊操作,只有隊尾可以進行入隊操作。
以單調不減隊列為例:佇列內的元素(e1,e2,e3...en)存在(e1<=e2<=e3<=...<=en)的關係,所以隊首元素e1一定是最小的元素。與優先佇列不同的是,當有乙個新的元素e入隊時,先要將隊尾的所有大於e的元素彈出,以保證單調性,再讓元素e入隊尾。
例如這樣一組數(1,3,2,1,5,6),進入單調不減佇列的過程如下:
1入隊,得到佇列(1);
3入隊,得到佇列(1,3);
2入隊,這時,隊尾的的元素3>2,將3從隊尾彈出,新的隊尾元素1<2,不用彈出,將2入隊,得到佇列(1,2);
1入隊,2>1,將2從隊尾彈出,得到佇列(1,1);
5入隊,得到佇列(1,1,5);
6入隊,得到佇列(1,1,5,6);
#includeusing namespace std;
const int maxn = 2e6 + 10;
#define inf 0x3f3f3f3f
typedef pairp;
typedef long long ll;
int dp[maxn];
int temp[maxn];
int main()
printf("%d\n",dp[x]);
}return 0;
}
HDU 3905 Sleeping 單調優化DP)
題目鏈結 這個狀態轉移想了會時間,dp i j 記錄前i分鐘學了j分鐘的取得的最大的分數,得到方程dp i j dp i k j k sum i sum i k l k j 這個果斷並不是只是乙個普通的dp,交上各種tle,然後發現問題了,應該需要需要優化。這個狀態方程神似以前單調佇列優化dp的轉移...
D 訓練技巧(dp,單調佇列優化)
有n天,每天訓練收益為ei,如果連續訓練了k天,則必須休息一天,問訓練的最大收益,1 n,k 1e5 dp i 表示第i天不訓練,前i天的最小損失,dp i min dp i dp j a i j i 1 i 2 i k 1 答案就是第n 1天不訓練,sum 前n天的最小損失嘍 這樣還是會超時,需要...
hdu 4374 dp 單調佇列優化
解法 dp 單調佇列!有乙個的樓房,從第一層某個位置出發上樓,每次能爬上一層樓也可以在同一層左右移動,但是在每一層的移動距離不能超過某個值。現在每個位置都有乙個數值,求從第一層出發到最後一層經過的路徑上最多能取到的最大價值。dp i j 表示 第i行,第j個數字的最大價值!sum i j 表示 第i...