$bzoj1021-SHOI2008\ Debt$ 循环的债务 $dp$

时间:2023-03-09 18:40:47
$bzoj1021-SHOI2008\ Debt$ 循环的债务 $dp$
  • 题面描述

    • \(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\)张钞票被交换过。没过多久他们就发现这是一个很棘手的问题,于是他们找到了精通数学的你为他们解决这个难题。
  • 输入格式

    • 输入的第一行包括三个整数:\(x_1\)、\(x_2\)、\(x_3\),\(-10^3\leq x_1,x_2,x_3\leq 10^3\),其中 \(x_1\)代表\(Alice\)欠\(Bob\)的钱(如果\(x_1\)是负数,说明\(Bob\)欠了\(Alice\)的钱)以此类推

      接下来有三行,每行包括6个自然数:

      \(a_{100}\) \(a_{50}\) \(a_{20}\) \(a_{10}\) \(a_{5}\) \(a_{1}\)
      \(b_{100}\) \(b_{50}\) \(b_{20}\) \(b_{10}\) \(b_{5}\) \(b_{1}\)
      \(c_{100}\) \(c_{50}\) \(c_{20}\) \(c_{10}\) \(c_{5}\) \(c_{1}\)

      \(a_{100}\)表示\(Alice\)拥有的\(100\)元钞票张数,\(b_{50}\)表示\(Bob\)拥有的\(50\)元钞票张数,以此类推。另外,我们保证有\(a_{10}+a_5+a_1\leq 30\),\(b_{10}+b_5+b_1\leq 30\),\(c_{10}+c_5+c_1\leq 30\),而且三人总共拥有的钞票面值总额不会超过\(10^3\)。

  • 输出格式

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

    • 首先看到这题,我们稍加思考便能够发现,这个问题的初状态每个人拥有的钱数,以及终状态每个人拥有的钱数是固定的。

    • 第一次看到题,我一直关注与钞票的交换上,只觉得这个交换方式十分复杂,没有办法用一种有效的方式转化。于是就\(YY\)了一个\(A^*\)出来,但过不了全部的点

      • 具体就是,把\(A^*\)的估价函数\(g(x)\)设为 不考虑每个人每种钱拥有的张数的情况下
        • \(\sum_{i=1}^3\)第\(i\)个人现有\(x\)元,终状态该人有\(y\)元,从\(x\)元变到\(y\)元最少要向他人交换几张钞票
      • 这一部分可以用无限背包做
    • 但像我们最初考虑该问题是想到的初状态与终状态固定,受到物理的保守力只需考虑始、末状态,不需考虑中间过程的启发,我们其实不需要知道这些钞票是如何进行换的,我们只关心换完之后每个人所拥有的钱。

    • 这样一来,我们就会发现,每种币值的钞票相对独立,因此我们将每种币值的钞票独立开来,成为每层的状态。

    • 如此一来,我们可以设计出这样的\(dp\)方程

      • 记\(f_{i,x,y,z}\)表示使用前\(i\)种币值的钞票进行交换后,三个人各有\(x,y,z\)元时最少的钞票交换次数,记\(b_i\)表示第\(i\)种钞票的币值,\(k_i\)表示每个人给出第\(i\)种钞票的张数(可正可负)

      • 则 他们三人之间交换第\(i​\)种钞票的总张数为\(chg=\frac{|k_1|+|k_2|+|k_3|}{2}​\)

      • \[f_{i,x-k_1*b_i,y-k_2*b_i,z-k_3*b_i}=f_{i-1,x,y,z}+chg\\
        保证k_1+k_2+k_3=三人拥有第i种钞票的总张数
        \]
    • 然后,我们不难发现\(x+y+z\)恒等三人拥有的总钱数

    • 因此我们可以降一维变成

      • \[f_{i,x-k_1*b_i,y-k_2*b_i}=f_{i-1,x,y}+chg\\
        k_3=三人拥有第i种钞票的总张数-k_1-k_2\\
        chg=\frac{|k_1|+|k_2|+|k_3|}{2}
        \]
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=1e3+5;
const int b[10]={0,100,50,20,10,5,1};
int mon[4][10];
int x1,x2,x3,s[4];
int sum;
int f[7][MAXN][MAXN];
int main(){
scanf("%d%d%d",&x1,&x2,&x3);
for (int i=1;i<=3;i++){
for (int j=1;j<=6;j++){
scanf("%d",&mon[i][j]);
sum+=mon[i][j]*b[j];
}
}
// cout<<"done"<<endl;
for (int i=1;i<=3;i++){
for (int j=1;j<=6;j++) s[i]+=mon[i][j]*b[j];
}
if (s[1]-x1+x3>sum||s[2]+x1-x2>sum||s[3]-x3+x2>sum) return printf("impossible\n"),0;
memset(f,63,sizeof(f)); f[0][s[1]][s[2]]=0;
for (int i=1;i<=6;i++){
for (int j=0;j<=sum;j++){
for (int k=0;k+j<=sum;k++){
if (f[i-1][j][k]>=1e9) continue;
int cnt=mon[1][i]+mon[2][i]+mon[3][i];
for (int x=0;x<=cnt;x++){
for (int y=0;y+x<=cnt;y++){
int z=cnt-x-y;
int lx=mon[1][i]-x;
int ly=mon[2][i]-y;
int lz=mon[3][i]-z;
int chg=(abs(lx)+abs(ly)+abs(lz))/2;
if (j-lx*b[i]+k-ly*b[i]>sum) continue;
if (j<lx*b[i]||k<ly*b[i]) continue;
f[i][j-lx*b[i]][k-ly*b[i]]=min(f[i][j-lx*b[i]][k-ly*b[i]],f[i-1][j][k]+chg);
}
}
}
}
}
int ans=f[6][s[1]-x1+x3][s[2]-x2+x1];
if (ans>=1e9) printf("impossible\n");
else printf("%d\n",ans);
return 0;
}

随机推荐

  1. SQL Server数据库大型应用解决方案总结(转)

    出处:http://tech.it168.com/a2012/0110/1300/000001300144.shtml [IT168 技术]随着互联网应用的广泛普及,海量数据的存储和访问成为了系统设计 ...

  2. SPOJ - AMR11J ——(BFS)

    The wizards and witches of Hogwarts School of Witchcraft found Prof. Binn's History of Magic lesson ...

  3. 安装pygame for Python3.5

    首先进入pygame官网下载页面:http://www.pygame.org/download.shtml  页面上提供的有py2.4-py2.7,py3.1-py3.2的版本(py2.4就是对应py ...

  4. jmeter- 性能测试3:聚合报告(Aggregate Report )

    jmeter-监听器-聚合报告样例: 字段说明: label:请求名称,自己定义的 #Samples:这次测试中一共发出了多少个请求,如果模拟20个用户,每个用户迭代20次,那么就是400(未设置持续 ...

  5. 7z文件格式及其源码的分析(二)

    这是第二篇, 第一篇在这里: 这一篇开始分析7z的源码结构. 一. 准备工作: 1. 源码下载: 可以从官方中文主页下载:http://sparanoid.com/lab/7z/. 为了方便, 这里直 ...

  6. Python 单元测试 增强系统健壮性

    问题背景交代 注意,JulyNovel只爬取免费小说,所有vip章节全部导航至起点网站,遵循robots协议,所有数据仅供学习用途,侵删 通过编写单元测试,提高JulyNovel系统可靠性 首先我们知 ...

  7. GRPC .netcore

    GRPC是Google发布的一个开源.高性能.通用RPC(Remote Procedure Call)框架.提供跨语言.跨平台支持.以下以一个.NET Core Console项目演示如何使用GRPC ...

  8. WinForm中DataGridView的使用(四) - 区分单双击事件

    虽然DataGridView单双击事件都有,但双击事件其实也会触发单击事件的处理,所以如果双击事件和单击事件的行为不同,或者双击时不想触发单击事件,或者单击事件会阻塞双击事件的处理时(比如单击后会有弹 ...

  9. C# winform 自定义鼠标光标

    第一种:(调用系统API)首先引入两个命名空间代码如下: using System.Runtime.InteropServices;using System.Reflection;导入API代码如下: ...

  10. SQLlite 分页

    如果我要去11-20的Account表的数据 Select * From Account Limit 9 Offset 10; 以上语句表示从Account表获取数据,跳过10行,取9行 嗯,我觉得这 ...