目錄全部分
這道題首先不考慮優化,我們該怎麼寫呢?顯然,這是乙個區間dp,我們可以利用記憶化搜尋來寫。
1、定義狀態:dp[i][j]表示前i頭分j段的最小價值。
2、狀態轉移方程:ans = min(ans,value(x,i) + dfs_dp(i + 1,left - 1));
這個狀態轉移方程和 這道題十分類似。
3、然後是計算有多少對羊:
做乙個桶sum表示乙個數有多少個。int value(int x,int y)
for(int i = mn;i <= mx; i++)
return ans;
}
部分分**(60分)
#include#define ll long long
using namespace std;
int n,k;
int a[1000001];
int dp[1001][1001];
int sum[10001];
inline ll read()
while(isdigit(ch))
if(las == '-') ans = -ans;
return ans;
}inline void write(ll x)
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
}int dui(int x)
int value(int x,int y)
for(int i = mn;i <= mx; i++)
return ans;
}int dfs_dp(int x,int left)
return dp[x][left] = ans;
}int flag = 1;
int main()
if(flag) else write(dfs_dp(1,k - 1));
return 0;
}
dp[i][j]=min(dp[i][j],dp[k][j-1]+calc(k+1,i)//calc表示價值
那麼對於每乙個決策點pl[i],我們不難發現:pl[i - 1] <= pl[i] <= pl[i + 1]
因此我們可以使用決策單調性優化,利用分治思想,暴力求解mid的決策點,從而縮小接下來列舉的範圍
求價值也是可以優化的,之前的方法有點慢,我們採用莫隊的思想(複雜度很玄,反正就是快了)對其進行優化,其實主要思想還是和桶一樣的void solve(int x,int y,int px,int py)
}solve(x,mid - 1,px,pl);
solve(mid + 1,y,pl,py);
}
ac**ll add(int x)
ll del(int x)
ll calc(int nl,int nr)
#includeusing namespace std;
#define ll long long
const int n = 1e5 + 100;
int m,n;
int a[n],buc[n];
int l = 1,r = 0;
ll sum = 0;
ll add(int x)
ll del(int x)
ll calc(int nl,int nr)
ll dp[n][30];
int now;
//pl[i - 1] <= pl[i] <= pl[i + 1]
void solve(int x,int y,int px,int py)
}solve(x,mid - 1,px,pl);
solve(mid + 1,y,pl,py);
}int main()
for(int i = 1; i <= n; i++)
for(int k = 2; k <= m; k++)
printf("%lld\n",dp[n][m]);
return 0;
}
動態規劃中級題解
二維的動態規劃解決 題目 假設在乙個n m的平面上,有n m個格仔,每個格仔中都有一定數量的蘋果,每次我們只能從某個格仔處向右或者向下走,注意不能超過地圖的限制,請問如何設計路徑才可以保證最後從起點到終點後獲得的蘋果數量最多 動態規劃解析 建立二維的dp陣列dp i j 表示走到map i j 格的...
動態規劃題解與分析
問題1 陣列的每個索引作為乙個階梯,第 i個階梯對應著乙個非負數的體力花費值 cost i 每當你爬上乙個階梯你都要花費對應的體力花費值,然後你可以選擇繼續爬乙個階梯或者爬兩個階梯。您需要找到達到樓層頂部的最低花費。在開始時,你可以選擇從索引為 0 或 1 的元素作為初始階梯。示例 1 輸入 cos...
動態規劃典型例題解析
動態規劃的主要思想是把問題劃分為乙個個子狀態,乙個狀態的最優解往往是基於其前乙個狀態的最優解。兩個狀態之間的關係,我們就稱之為狀態轉移方程。這裡引出了狀態和狀態轉移方程的概念 狀態是乙個當前的值,這個值是通過前乙個值以及狀態轉移方程推得的。在解決動態規劃問題的時候,我們往往會把問題建模為乙個一維陣列...