簡單問題
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應用記錄狀態 記憶化搜尋 n*mint 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);
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--)乙個容量為m的揹包,有n個物品,第i個物品的體積為wi,價值為ci,有2個。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的情況下價值總和最大。
記憶化搜尋
const乙個容量為m的揹包,有n個物品,第i個物品的體積為wi,價值為ci,有ki個。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的情況下價值總和最大。
記憶化搜尋
int dfs(int x,int遞推y)
return
dp[x][y];
}dfs(
1,0);
for (i=n; i>=1; i--)有n家店,每家店都有m臺機器,第i家店購買j臺機器花費a[i][j]元(可能存在a[i][j]>a[i][j+1]),要購買總共m臺機器,求最小花費。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]
搜尋
//小小的變形機器分配
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--)給定n個非負整數,選擇其中若干數字,使得每連續k個數中至少有乙個數被選出。for(int j=0;j<=m;j++)
ans=dp[1][0]
要求選擇的數字之和盡可能小。
搜尋
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);
/*給定乙個n*m的矩陣a(n<=m),求乙個序列a1,a2,…,an滿足1<=a1搜尋dp[n+1]=0;
dp[1] dp[2] dp[3] .. dp[1+k]
*/for (i=n; i>=0; i--)
dp[0]
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.聽張老師的講座,感覺還是獲益匪淺。他說我們學校的軟體工程專業現況是有實力與清華北大媲美的,這讓我感到十分榮幸,雖然沒有親自去過清華北大,但這兩所學校的名氣確實是如雷貫耳的,瞬間覺得我還是走上了乙個高富帥的專業。但是,以後的事情還是需要我繼續努力堅持才...