$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\)元最少要向他人交换几张钞票
- 这一部分可以用无限背包做
- 具体就是,把\(A^*\)的估价函数\(g(x)\)设为 不考虑每个人每种钱拥有的张数的情况下
但像我们最初考虑该问题是想到的初状态与终状态固定,受到物理的保守力只需考虑始、末状态,不需考虑中间过程的启发,我们其实不需要知道这些钞票是如何进行换的,我们只关心换完之后每个人所拥有的钱。
这样一来,我们就会发现,每种币值的钞票相对独立,因此我们将每种币值的钞票独立开来,成为每层的状态。
如此一来,我们可以设计出这样的\(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;
}
随机推荐
- 编写高质量代码改善C#程序的157个建议——建议79:使用ThreadPool或BackgroundWorker代替Thread
建议79:使用ThreadPool或BackgroundWorker代替Thread 使用线程能极大地提升用户体验度,但是作为开发者应该注意到,线程的开销是很大的. 线程的空间开销来自: 1)线程内核 ...
- 通过python实现wc基本功能
---恢复内容开始--- 1.Github项目地址: https://github.com/zhg1998/ww/blob/master/wc.py 2.项目相关要求: 写一个命令行程序,模仿已有wc ...
- select2的一些隐藏功能
select 3.5版本的说明文档里面存在 http://select2.github.io/select2/index.html option选项 sortResults query为查询字符串
- 【装饰者模式】Decorator Pattern
装饰者模式,这个模式说我一直记忆深刻的模式,因为Java的IO,我以前总觉得Java的IO是一个类爆炸,自从明白了装饰者模式,Java的IO体系让我觉得非常的可爱,我们现在看看什么是装饰者,然后再来看 ...
- Reporting Service服务SharePoint集成模式安装配置(7、配置SharePoint2010产品)
在第3步安装完成SharePoint2010产品后,没有选择[立即安装产品配置向导],这一小节将单独配置SharePoint2010产品数据库(管理中心). 1)启动SharePoint 2010 产 ...
- atan2()如何转换为角度
atan2()如何转换为角度 Math.atan2()函数返回点(x,y)和原点(0,0)之间直线的倾斜角.那么如何计算任意两点间直线的倾斜角呢?只需要将两点x,y坐标分别相减得到一个新的点(x2-x ...
- Open Interface Service WCF三种通信模式
WCF三种通信模式 一.请求响应模式: 概念:客户端发送请求,一直等待服务端响应,在此期间处于等待(假死)状态:直到服务器响应,才能继续执行其他的操作: 即使返回值是void 也属于请求与答复模式. ...
- 在一台服务器上搭建相对高可用HiveServer实践
本文来自网易云社区 作者:刘杰 问题及原因 组里之前搭建了一个hiveserver提供给猛犸上的ETL程序调用,hiveserver隔三差五地挂掉重启,网上查了些资料,也咨询了猛犸那边维护hivese ...
- APIO2014 连珠线
题目链接:戳我 换根DP 由于蒟蒻不会做这个题,所以参考了大佬. 本来想的是有三种情况,一种是该节点不作为两个蓝线的中点(我们称这种不是关键节点),一种是该节点作为关键点.连两个子节点,一种是作为关键 ...
- python 注释 与 windows 上用tab 自动补齐设置
python的注释 单行注释:用# 多行代码用:“”“ 中间为你要注释的解释 ”“” # 我是单行注释 我是一个#号 print("hello,word") "&quo ...