給出三個人之間的欠錢關係和他們各自持有的錢幣種類和個數,求能不能各自把錢還清,如果不能輸出」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表示禮物,小明想讓你幫他算出惡搞指數,即最少需要拆多少個盒子才能拿到禮物。輸入格式 輸...