BZOJ 1021 迴圈的債務

2021-07-28 07:41:48 字數 1505 閱讀 8157

給出三個人之間的欠錢關係和他們各自持有的錢幣種類和個數,求能不能各自把錢還清,如果不能輸出」impossible」,如果能輸出最小的給錢張數。

dp太神了!(弱菜自帶遇dp必跪flag)總之就是dp。  

可以按錢幣種類劃分階段,那麼方程可以為dp

[i][

j][k

] 表示用上了前i種錢幣,達到了讓第乙個人有j塊錢,第二個人有k塊錢(因為總的錢數是一定的,確定了這兩個第三個就確定了)所用的最小交換次數。那麼最後的an

s 就是dp

[6][

tj][

tk] 這樣。tj

和tk 可以分別用sa

−b+c

和sb−

c+a 得到sa

是初始時給出的第乙個人所擁有的錢數,sb

同理(即初始的減去給別人的加上別人給他的),最後就考慮如何轉移了。

初始值dp[

0][s

a][s

b]=0

其它都是in

f 即最大值,轉移就是列舉所有的情況像揹包(?)一樣去轉移。這裡需要明確一點,如果我們已知了第乙個人為了達到j錢給錢或者拿錢的張數和第二個人為了達到k錢給錢或者拿錢的張數,那麼這個轉移中需要統計的總共交換錢幣張數就是(a

bs(d

elta

a)+a

bs(d

elta

b)+a

bs(d

elta

a+de

ltab

))/2

,這個式子具體就是a改變的加上b改變的加上c改變的最後除去重複的。然後列舉一下

j 和

k,接著列舉一下當前錢幣數目,就可以進行轉移,其實這部分轉移看**比較容易理解,口述真的感人。

#include 

#include

#include

#include

#define inf 33686018

using

namespace

std;

const

int maxn = 1010;

int val[7] = ,cnt[maxn][maxn],d[maxn],e[maxn],sum,a,b,c,dp[3][maxn][maxn];

int main()

}int ta = d[1] - a + c,tb = d[2] - b + a;

if(ta < 0 || tb < 0 || sum - ta - tb < 0)

memset(dp[0],2,sizeof(dp[0]));int pre = 0,now = 0;dp[0][d[1]][d[2]] = 0;

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

}}

if(dp[now][ta][tb] == inf)

else

printf("%d\n",dp[now][ta][tb]);

return

0;}

BZOJ1021 SHOI2008 迴圈的債務

alice bob和cynthia總是為他們之間混亂的債務而煩惱,終於有一天,他們決定坐下來一起解決這個問題。不過,鑑別鈔票的真偽是一件很麻煩的事情,於是他們決定要在清還債務的時候盡可能少的交換現金。比如說,al ice欠bob 10元,而cynthia和他倆互不相欠。現在假設alice只有一張50...

1021 統計字元

題目描述 統計乙個給定字串中指定的字元出現的次數。輸入 測試輸入包含若干測試用例,每個測試用例包含2行,第1行為乙個長度不超過5的字串,第2行為乙個長度不超過80的字串。注意這裡的字串包含空格,即空格也可能是要求被統計的字元之一。當讀到 時輸入結束,相應的結果不要輸出。輸出 對每個測試用例,統計第1...

1021 惡搞指數

題目描述 小明的朋友過生日,小明準備了一件禮物,不過小明想惡搞一下他的朋友,所以他準備了一堆盒子,其中有乙個盒子裡面裝了禮物。盒子裡面可以再放零個或者多個盒子。假設放禮物的盒子裡不再放其他盒子。用 表示乙個盒子,b表示禮物,小明想讓你幫他算出惡搞指數,即最少需要拆多少個盒子才能拿到禮物。輸入格式 輸...