**於寧波市程式設計競賽複賽(初中組)
n≤5000,m≤n,顯然o(n^3)的複雜度不能接受,那麼考慮o(n^2)或者o(n^2*lg(n))的解法。最少需要消耗多少能量,看起來是乙個好像具有最優子結構的問題,那麼嘗試是否能用動態規劃來求解。
仔細分析,可以發現最後乙隻猴子最優情況下肯定是爬上最後一棵樹,那麼這樣就存在了重複子問題,動態規劃無疑了。
考慮狀態的表示,我們用dp[i][j]來表示前i只猴子爬上前j顆樹,並且保證,每棵樹至少有乙隻猴子的最小花費。
那麼狀態轉移方程就可以表示成
dp[i][j]=min(dp[k][j-1]+sum[i][j]-sum[k][j]),
此處sum[i][j]表示前i只猴子都爬上第j顆樹的花費。
至此,我們已經找到了解法。但是此處i,j,k三層迴圈,總的複雜度達到了o(n^3),只能通過前一半的測試資料,因此還需進行優化。
考慮乙個問題,在計算dp[i][j]的時候,我們列舉了k,這裡列舉k是否有必要呢?dp[i][j]=dp[k][j-1]+sum[i][j]-sum[k][j],無非表示前i只猴子中的前k只上了前j-1棵樹,剩下的上了第j棵樹。我們完全可以用dp[i][j]=dp[i-1][j]+sum[i][j]-sum[i-1][j]來表示。
因為dp[i-1][j]已然包含了dp[k][j-1]的情況。
那麼轉移方程可以進一步簡化成
dp[i][j]=min(dp[i-1][j-1],dp[i-1][j])+dis(i,j)。
這樣我們就把時間複雜度降低到了o(n^2)。
但是還沒有結束,此題對於記憶體有著一定的限制,開乙個5000*5000的陣列是會超記憶體的,我們觀察到,dp[x][j]只與dp[x][j-1]存在關係,與dp[x][j-2],dp[x][j-3]…均無遞推關係。因此我們可以重複利用之前賦值過的空間,即滾動陣列降低空間複雜度,那麼轉移方程就變成了
dp[i][j%2]=min(dp[i-1][j-1],dp[i-1][j])+dis(i,j);
#include
#include
#include
#include
#include
#include
#include
#define ll long long
using
namespace
std;
const
int maxn=5005;
const ll inf=1e18;
ll dp[maxn][2];
ll sum[maxn];
ll mokey[maxn], tree[maxn];
ll dis(ll mp,ll tp)
int main()
}printf("%lld\n",dp[n][m%2]);
return
0;}
28屆寧波市中小學生程式設計競賽複賽 初中組
於寧波市程式設計競賽複賽 初中組 n 500,000,顯然對於這麼大的n,o n 2 的解法都不夠。那麼考慮o n 或者o n lg n 的解法,動態規劃?貌似可行,但狀態怎麼表示?左對齊?右對齊?除此,要怎麼進行轉移呢,畢竟a和b的範圍也相當大,即便進行hash,最多也有500,000?繼續分析發...
30屆寧波市中小學生程式設計競賽複賽 初中組
於寧波市程式設計競賽複賽 初中組 單個班級內,最優排列方案的不整齊度 max ai min ai 2,即按高度進行排序,此時應當最優 感覺是個不等式證明?那麼排列方案的優劣與羊的具體數量無關,與各只羊的高度無關,至於最大高度與最小高度的差值有關。讓所有小羊按高度排列,此時可以將整個佇列看做一條線段,...
中小學生程式設計
近幾年以來,發布了多個推廣少兒程式設計教育的紅本政策,市面上也湧出了一大批少兒程式設計教育 機械人程式設計教育的機構。格物斯坦認為 大多數家長都不太名二者之間有什麼區別,很多家長感覺是機械人程式設計更高大上,但又不知道是不是這麼一回事。其實,少兒程式設計類產品,大體上分為兩類 純軟體類或軟硬體結合類...