BZOJ 1021 [Debt circulating debt]

Title

Title

  A, B, C owe each other some money, each person holds some banknotes with a denomination of \ (100,50,20,10,5,1 \) , the total amount of banknotes does not exceed \ (1000 \) , please pay off The minimum number of paper currency exchanges for debt.

answer

  DP. Use \ (dp_ {i, j} \) to represent the minimum number of paper currency exchanges where A holds the amount of \ (i \) and B holds the amount of \ (j \) . Obviously, a bill can be handed over at most once, and any change of hands can be replaced by a one-step operation, so there is no need to worry about the aftereffect of handing over bills, it can be DP.

  There are two ways of thinking, one is to do DP once for each banknote, and the other is to allocate all the banknotes of the same denomination in order from the largest to the smallest. Although the latter seems to have a higher complexity, the advantage is that when dealing with each denomination , the initial wealth of A (B ) is not processed by \ (dp_ {i, j} \) which is not \ (+ \ infty \) . The least common multiple of the denomination is congruent. Because this question has many restrictions and complicated conditions, it is not meaningful to discuss the specific complexity. From the practical results, the first method card can often be passed, but the time of the second method is slightly more ample. The implementation code for the second method is posted here.

Code

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e3+5,inf=1e9;
const int val[6]={100,50,20,10,5,1},mod[6]={10000,100,50,10,10,5};
int dp[maxn][maxn],tmp[maxn][maxn];
int a[3][6],b[3],p,q;
int _abs(int n){ return n<0?-n:n; }
inline void update(int &a,int b){ a=a<b?a:b; }
void give(int a,int b,int c,int v,int m){
    int i,j,k;
    int x,y,z,t=a+b+c;
    for (x=p%m;x<maxn;x+=m) for (y=q%m;y<maxn;y+=m) tmp[x][y]=dp[x][y];
    for (x=p%m;x<maxn;x+=m) for (y=q%m;y<maxn;y+=m) if (tmp[x][y]<inf){
        for (i=0;i<=t;i++) for (j=t-i;j>=0;j--)
            update(dp[x-(a-i)*v][y-(b-j)*v],tmp[x][y]+_abs(a-i)+_abs(b-j)+_abs(a+b-i-j));
    }
}
int main(){
    int i,j;
    int x,y,z;
    scanf("%d%d%d",&x,&y,&z);
    for (i=0;i<3;i++) for (j=0;j<6;j++){
        scanf("%d",&a[i][j]); b[i]+=a[i][j]*val[j];
    }
    for (i=0;i<maxn;i++) for (j=0;j<maxn;j++)
        dp[i][j]=inf;
    dp[b[0]][b[1]]=0;
    p=b[0]; q=b[1];
    b[0]-=x-z; b[1]-=y-x; b[2]-=z-y;
    for (i=0;i<6;i++) give(a[0][i],a[1][i],a[2][i],val[i],mod[i]);
    if (b[0]<0||b[0]>=maxn||b[1]<0||b[1]>=maxn){
        puts("impossible"); return 0;
    }
    if (dp[b[0]][b[1]]==inf) puts("impossible");
    else printf("%d\n",dp[b[0]][b[1]]/2);
    return 0;
}

Guess you like

Origin www.cnblogs.com/Kilo-5723/p/12717234.html