小A的煩惱 揹包DP

2022-03-11 13:59:03 字數 1555 閱讀 4471

題意:有n(n<=1000)個紙牌,每個紙牌分為上下兩格,且每格可有1-10個點,所有上格加起來的和為p1,所有下格加起來的和為p2,求想得到|p1-p2|的最小值,需要翻轉多少次

給出的題解是:

正常的做法是用 dp,可以用二維的 dp 陣列,在這里用了一維陣列進行 dp。 dp[i] 表示上下相差為i 時的最小操作次數。 因為是上下相差所以可能出現負數,將整個陣列右移 位, 理論上是上下相差的最大值 在實際程式中 dp[i+n] 是上面 dp[i] 所表示的意義

每次翻轉會使上下差值改變,這個改變值記錄為 a[j],改變值應該是初始值的兩倍。 狀態轉移方程就是 dp[i-a[j]]=min(dp[i-a[j]],dp[i]+1) 同時又考慮到差值有負數的情況,所以根據初始差值情況分類討論一下,不同情況dp的方向 不同。

最後在 dp 陣列中從 n 向兩側尋找能達到的最小值輸出即可。

二維的**也很好懂

#includeusing

namespace

std;

int dp[1005][20005

];int a[1005

];const

static

int inf=0x7fffff

;int

main()

int t=tx-ty;

int n=1000

;

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

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

dp[i][j]=inf;

dp[0][t+n]=0

;

for(int i=1;i<=n;i++)}}

intans;

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

}cout

<}

但在轉換成一維的時候遇到不少問題,花了很多時間,第乙個點在於一維的時候為了考慮a[i]的正負,還需要分情況討論

第二個點在於分情況討論後其狀態轉移方程還是得一致

#includeusing

namespace

std;

typedef

long

long

ll;const

int inf=1

<<30

;const

int maxn=1e3+7

;int

a[maxn];

int dp[20010];//

上下差為i(此時陣列內數為10000+i)時的最小操作次數

intmain()

int t=tx-ty;

for(int i=0;i<=20000;i++)dp[i]=inf;

dp[1000+t]=0;//

初始狀態

for(int i=1;i<=n;i++)

}else

for(int j=20000;j>=a[i];j--)

}intans;

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

} cout

return0;

}

揹包 DP 揹包

揹包 題目 是dp中較為常見的題目 分為 0 1 揹包 完全揹包 和多重揹包 這三類 是越來越深入的首先來介紹一下 0 1揹包 首先 0 1 揹包的含義是 給你乙個容量位m的揹包 然後給你n個物品 每個物品具有一定價值和一定重量 會站一定的揹包空間 答案是在n個物品中那幾個 然後使得到的價值最大 首...

簡單的煩惱 揹包問題

第一行乙個整數t t 23 表示資料組數。在每組輸入資料中,第一行有兩個正整數,n n 200 t t 80000 分別表示歌單中歌曲的數目,和題目描述中的t。第二行中有n個正整數a i a i 400 表示每首歌曲的時間長度。對於每組資料,輸出乙個ans,表示最多能聽多長時間的歌曲。示例1 複製1...

揹包dp之01揹包

現在我們有n個配件,他們有不同的價值.但是我們揹包的容量是有限的,因為我們只有乙個一級包,所以我們最多可以裝v重量的東西.但是為了能更好的吃到雞 不存在的 我們要攜帶更有價值的配件,請問我們最多能拿多少價值的配件來當快遞員呢?輸入的第一行是t,表示有一共要打t場比賽.每組資料由三行組成.第一行包含兩...