動態規劃(冬令營課堂筆記)

2021-07-30 12:57:15 字數 4649 閱讀 1818

簡單問題

01揹包

012揹包

部分揹包

機器分配

烽火傳遞

花店櫥窗問題

乙個容量為m的揹包,有n個物品,第i個物品的體積為wi,價值為ci。選擇若干物品,使得體積總和不超過m的情況下價值總和最大。

n<=100,m<=10000。

搜尋  複雜度為2^n

void dfs(int x,int y,int z)//

當前物品編號,當前容量,當前價值

dfs(x+1,y+w[x],z+c[i]);

dfs(x+1

,y,z);

}

如果前兩維相同,只需選擇第三維的最大值

小小的變形

const

int inf=0x7f

;int dfs(int x,int

y) ans=max(dfs(x+1,y+w[x])+c[x],dfs(x+1

,y));

return

ans;

}dfs(

1,0);

加乙個陣列記錄

const

int inf=0x7f

;int dfs(int x,int

y) dp[x][y]=max(dfs(x+1,y+w[x])+c[x],dfs(x+1

,y));

return

dp[x][y];

}dfs(

1,0);

應用記錄狀態  記憶化搜尋 n*m

const

int inf=0x7f

;int dfs(int x,int

y)

if(dp[x+1][y+w[x]]) //

選該物品

dp[x][y]=max(dp[x+1][y+w[x]]+c[x],dp[x][y]);

else

dp[x][y]=max(dfs(x+1,y+w[x])+c[x],dp[x][y]);

if(dp[x+1][y]) //

不選該物品

dp[x][y]=max(dp[x+1][y]+c[x],dp[x][y]);

else

dp[x][y]=max(dfs(x+1,y))+c[x],dp[x][y]);

return

dp[x][y];

}dfs(

1,0);

遞迴變遞推

先寫出搜尋

最大/最小值 存放到陣列中

後面遞迴該狀態時 直接使用陣列中的值來代替

o(dfs裡的狀態個數*轉移的時間複雜度)

找邊界

找遞推方法(順序還是逆序)

轉移(推轉移方程)

搜尋->記憶化搜尋->遞迴變遞推

for(int i=n;i>=1;i--)

for(int j=0;j<=m;j++)

dp[i][j]=max(dp[i+1][j],dp[i+1][j+w[i]]+c[i]);

ans=dp[1][0

]

乙個容量為m的揹包,有n個物品,第i個物品的體積為wi,價值為ci,有2個。

選擇若干物品,使得體積總和不超過m的情況下價值總和最大。

記憶化搜尋

const

int inf=0x7f

;int dfs(int x,int y,int

z)

if(dp[x+1][y]) //

乙個都不選

dp[x][y]=max(dp[x][y],dp[x+1

][y]);

else

dp[x][y]=max(dp[x][y],dfs(x+1

,y));

if(dp[x+1][y+w[x]]) //

選乙個

dp[x][y]=max(dp[x][y],dp[x+1][y+w[x]])+c[x]);

else

dp[x][y]=max(dp[x][y],dfs(x+1,y+w[x])+c[x]);

if(dp[x+1][y+w[x]]) //

選兩個

dp[x][y]=max(dp[x][y],dp[x+1][y+2*w[x]])+2*c[x]);

else

dp[x][y]=max(dp[x][y],dfs(x+1,y+2*w[x])+2*c[x]);

return

dp[x][y];

}dfs(

1,0);

乙個容量為m的揹包,有n個物品,第i個物品的體積為wi,價值為ci,有ki個。

選擇若干物品,使得體積總和不超過m的情況下價值總和最大。

記憶化搜尋

int dfs(int x,int

y)

return

dp[x][y];

}dfs(

1,0);

遞推

for (i=n; i>=1; i--)

for (j=0; j<=m; j++)

for (l=0; l<=k[i]; l++)

dp[i][j]=max(dp[i][j],dp[i+1][j+l*w[i]]+l*c[i]);

dp[1][0]

有n家店,每家店都有m臺機器,第i家店購買j臺機器花費a[i][j]元(可能存在a[i][j]>a[i][j+1]),要購買總共m臺機器,求最小花費。

搜尋

//

機器分配

dfs(int x,int y,int

z)

for(int i=0;i<=m;i++)

dfs(x+1;y+i,z+a[x][i]);

}dfs(

1,0,0);

小小的變形

//

機器分配

int dfs(int x,int

y)

for(int i=0;i<=m;i++)

dp[x][y]=min(dp[x][y],dfs(x+1,y+i)+a[x][i]);

return

dp[x][y];

}dfs(

1,0);

記憶化搜尋

//

機器分配

int dfs(int x,int

y)

for(int i=0;i<=m;i++)

if(dp[x+1][y+i])

dp[x][y]=min(dp[x][y],dp[x+1][y+i]+a[x][i]);

else

dp[x][y]=min(dp[x][y],dfs(x+1,y+i)+a[x][i]);

return

dp[x][y];

}dfs(

1,0);

遞推

for(int i=n;i>=1;i--)

for(int j=0;j<=m;j++)

ans=dp[1][0]

給定n個非負整數,選擇其中若干數字,使得每連續k個數中至少有乙個數被選出。

要求選擇的數字之和盡可能小。

搜尋

void dfs(int x,int

y)

for(int i=x+1;i<=min(n+1,x+k);i++)

dfs(i,y+a[i]);//

i是下乙個

}dfs(

0,0);

記憶化

int dfs(int

x)dfs(

0);

遞推

/*

dp[n+1]=0;

dp[1] dp[2] dp[3] .. dp[1+k]

*/for (i=n; i>=0; i--)

dp[0]

給定乙個n*m的矩陣a(n<=m),求乙個序列a1,a2,…,an滿足1<=a1搜尋

void dfs(int x,int y,int

z)

for(int i=y+1;i<=m;i++)

dfs(x+1,i,z+a[x+1

][i]);

}dfs(

0,0,0);

記憶化搜尋

int dfs(int x,int

y)

for(int i=y+1;i<=m;i++)

}dfs(

0,0);

遞推

/*

dp[n+1][m+1]=0; dp[n+1][0~m]=-inf;

dp[1] dp[2] dp[3]

*/for (i=n; i>=0;i--)

for (j=0; j<=m+1; j++)

for (k=j+1; k<=m+1; k++)

dp[i][j]=max(dp[i][j],dp[i+1][k]+a[i+1

][k]);

cout

<0][0];

動態規劃(冬令營課堂筆記)

簡單問題 01揹包 012揹包 部分揹包 機器分配 烽火傳遞 花店櫥窗問題 乙個容量為m的揹包,有n個物品,第i個物品的體積為wi,價值為ci。選擇若干物品,使得體積總和不超過m的情況下價值總和最大。n 100,m 10000。搜尋 複雜度為2 n void dfs int x,int y,int ...

冬令營頹廢筆記

主要用於處理不便於合併兩個區間的問題。題面solution 本題為序列分塊經典題。顯然要先離散化,對序列分塊。預處理出 cnt i j 到 i 塊顏色為 j 的總數 f i j 從塊 i 到 j 的眾數 列舉塊的開頭,掃一遍即可 num i j 從塊 i 到 j 的眾數是什麼數 然後我們在詢問的時候...

2015 2 1冬令營日誌

今天的任務 1.寫一篇部落格。2.寫乙個週報。3.聽張老師的講座,感覺還是獲益匪淺。他說我們學校的軟體工程專業現況是有實力與清華北大媲美的,這讓我感到十分榮幸,雖然沒有親自去過清華北大,但這兩所學校的名氣確實是如雷貫耳的,瞬間覺得我還是走上了乙個高富帥的專業。但是,以後的事情還是需要我繼續努力堅持才...