zoukankan      html  css  js  c++  java
  • BZOJ 1021 循环的债务

    Description

    Alice、Bob和Cynthia总是为他们之间混乱的债务而烦恼,终于有一天,他们决定坐下来一起解决这个问题。不过,鉴别钞票的真伪是一件很麻烦的事情,于是他们决定要在清还债务的时候尽可能少的交换现金。比如说,Alice欠Bob 10元,而Cynthia和他俩互不相欠。现在假设Alice只有一张50元,Bob有3张10元和10张1元,Cynthia有3张20元。一种比较直接的做法是:Alice将50元交给Bob,而Bob将他身上的钱找给Alice,这样一共就会有14张钞票被交换。但这不是最好的做法,最好的做法是:Alice把50块给Cynthia,Cynthia再把两张20给Alice,另一张20给Bob,而Bob把一张10块给C,此时只有5张钞票被交换过。没过多久他们就发现这是一个很棘手的问题,于是他们找到了精通数学的你为他们解决这个难题。

    Input

    输入的第一行包括三个整数:x1、x2、x3(-1,000≤x1,x2,x3≤1,000),其中 x1代表Alice欠Bob的钱(如果x1是负数,说明Bob欠了Alice的钱) x2代表Bob欠Cynthia的钱(如果x2是负数,说明Cynthia欠了Bob的钱) x3代表Cynthia欠Alice的钱(如果x3是负数,说明Alice欠了Cynthia的钱)接下来有三行,每行包括6个自然数: a100,a50,a20,a10,a5,a1 b100,b50,b20,b10,b5,b1 c100,c50,c20,c10,c5,c1 a100表示Alice拥有的100元钞票张数,b50表示Bob拥有的50元钞票张数,以此类推。另外,我们保证有a10+a5+a1≤30,b10+b5+b1≤30,c10+c5+c1≤30,而且三人总共拥有的钞票面值总额不会超过1,000。

    Output

    如果债务可以还清,则输出需要交换钞票的最少张数;如果不能还清,则输出“impossible”(注意单词全部小写,输出到文件时不要加引号)。

    Sample Input

    输入一
    10 0 0
    0 1 0 0 0 0
    0 0 0 3 0 10
    0 0 3 0 0 0
    输入二
    -10 -10 -10
    0 0 0 0 0 0
    0 0 0 0 0 0
    0 0 0 0 0 0

    Sample Output

    输出一
    5
    输出二
    0

    HINT

    对于100%的数据,x1、x2、x3 ≤ |1,000|。

    Source

    这是一道比较裸的dp(蒟蒻的我居然没看出来)。f[i][j][k]表示前i种面值,A有j元,B有k元的最少交换次数。然后,你懂的(每种面值互相独立),就是转移有点难写,但是,我们是理论计算机科学家,从来不关心算法的实现。

     1 #include<cstring>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 using namespace std;
     5 
     6 #define inf (1<<25)
     7 #define maxn 1010
     8 int price[8] = {0,100,50,20,10,5,1};
     9 int all,x[5],have[5][8],aim[5],f[8][maxn][maxn];
    10 
    11 inline int ord(int a) { if (a+1 <= 3) return a+1; return 1; }
    12 
    13 inline void updata(int &now,int key) { if (now > key) now = key; }
    14 
    15 inline void dp()
    16 {
    17     int i,x,y,s[4];
    18     for (i = 0;i < 6;++i)
    19         for (s[1] = 0;s[1] <= all;++s[1])
    20             for (s[2] = all - s[1];s[2] >= 0;--s[2])
    21             {
    22                 if (f[i][s[1]][s[2]] > inf) continue;
    23                 s[3] = all - s[1] - s[2];
    24                 for (x = 0;x <= have[1][i+1];++x)
    25                 {
    26                     if (x * price[i+1] > s[1]) break;
    27                     for (y = 0;y <= have[2][i+1];++y)
    28                     {
    29                         if (y * price[i+1] > s[2]) break;
    30                         updata(f[i+1][s[1]-x*price[i+1]][s[2]-y*price[i+1]],f[i][s[1]][s[2]]+x+y);
    31                     }
    32                 }
    33                 for (x = 0;x <= have[1][i+1];++x)
    34                 {
    35                     if (x * price[i+1] > s[1]) break;
    36                     for (y = 0;y <= have[3][i+1];++y)
    37                     {
    38                         if (y * price[i+1] > s[3]) break;
    39                         updata(f[i+1][s[1]-x*price[i+1]][s[2]+(x+y)*price[i+1]],f[i][s[1]][s[2]]+x+y);
    40                     }
    41                 }
    42                 for (x = 0;x <= have[2][i+1];++x)
    43                 {
    44                     if (x * price[i+1] > s[2]) break;
    45                     for (y = 0;y <= have[3][i+1];++y)
    46                     {
    47                         if (y * price[i+1] > s[3]) break;
    48                         updata(f[i+1][s[1]+(x+y)*price[i+1]][s[2]-x*price[i+1]],f[i][s[1]][s[2]]+x+y);
    49                     }
    50                 }
    51                 for (x = 0;x <= have[1][i+1];++x)
    52                 {
    53                     if (x * price[i+1] > s[1]) break;
    54                     for (y = 0;y <= x;++y) 
    55                         updata(f[i+1][s[1]-x*price[i+1]][s[2]+y*price[i+1]],f[i][s[1]][s[2]]+x); 
    56                 }
    57                 for (x = 0;x <= have[2][i+1];++x)
    58                 {
    59                     if (x * price[i+1] > s[2]) break;
    60                     for (y = 0;y <= x;++y)
    61                         updata(f[i+1][s[1]+y*price[i+1]][s[2]-x*price[i+1]],f[i][s[1]][s[2]]+x);
    62                 }
    63                 for (x = 0;x <= have[3][i+1];++x)
    64                 {
    65                     if (x * price[i+1] > s[3]) break;
    66                     for (y = 0;y <= x;++y)
    67                         updata(f[i+1][s[1]+y*price[i+1]][s[2]+(x-y)*price[i+1]],f[i][s[1]][s[2]]+x);
    68                 }
    69             }
    70 }
    71 
    72 int main()
    73 {
    74     memset(f,0x7,sizeof(f)); int i,j;
    75     for (i = 1;i <= 3;++i) scanf("%d",x+i);
    76     for (i = 1;i <= 3;++i)
    77         for (j = 1;j <= 6;++j) scanf("%d",have[i]+j),aim[i] += price[j]*have[i][j];
    78     all = aim[1] + aim[2] + aim[3];
    79     f[0][aim[1]][aim[2]] = 0;
    80     for (i = 1;i <= 3;++i) aim[i] -= x[i],aim[ord(i)] += x[i];
    81     for (i = 1;i <= 3;++i) if (aim[i] < 0) printf("impossible"),exit(0);
    82     dp();
    83     if (f[6][aim[1]][aim[2]] < inf) printf("%d",f[6][aim[1]][aim[2]]);
    84     else printf("impossible");
    85     return 0;
    86 }
    View Code
  • 相关阅读:
    loj#6433. 「PKUSC2018」最大前缀和(状压dp)
    PKUWC2019游记
    10. Regular Expression Matching
    9. Palindrome Number
    8. String to Integer (atoi)
    7. Reverse Integer
    6. ZigZag Conversion
    5. Longest Palindromic Substring
    4. Median of Two Sorted Arrays
    3. Longest Substring Without Repeating Characters
  • 原文地址:https://www.cnblogs.com/mmlz/p/4269977.html
Copyright © 2011-2022 走看看