参考这里:
允许找零应该怎么做: http://www.4ucode.com/Study/Topic/2119680
实在不会看这里: http://hi.baidu.com/wy_erhu/blog/item/057fed168e02660d972b4331.html
我最初的代码是不考虑找零的完全背包:(代码)
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
/*
心得:
1. (多重)物品编号 编号从1开始比较好写代码
2. 这个代码的错误是: 只考虑付款相加的情况,不考虑找零
*/
#define INF 1<<27
int w[7]; //value of each banknote
int f[7][101]; //f[i][j]: w[1...i] considered, the least # of banknotes to amount up to j
//DP(完全背包)
void solve(){
memset(f,-1,sizeof(f));
int i,j,k,k_max;
//DP(完全背包) init
f[0][0]=0;
//DP(完全背包)
for(i=1;i<=6;i++){
k_max=100/w[i];//∴币种w[i]的数量范围是[0,k_max]
for(j=0;j<=100;j++){
/*
初始化:
f[i][j]=-1
f[0~6][0]=0
状态转移方程:
f[i][j]=min{f[i-1][j-k*w[i]]+k}, 0<=k<=100/w[i]
*/
int temp=INF;
for(k=0;k<=k_max;k++){
if(j-k*w[i]>=0 && f[i-1][j-k*w[i]]!=-1 && f[i-1][j-k*w[i]]+k<temp){
temp=f[i-1][j-k*w[i]]+k;
}
}
f[i][j]=temp;
}
}
//题目保证结束时,f[5][0~100]都能找到解 ——至少可以用全部为1的币种来构造:)
}
void output(){
double sum=0;
int max=-1;
int i;
for(i=1;i<=100;i++){
printf("%d\t",f[6][i]);
sum+=f[6][i];
if(f[6][i]>max)
max=f[6][i];
}
printf("%lf %d\n",sum/100, max);
}
int main(){
int cases;
scanf("%d",&cases);
while(cases-->0){
int i;
for(i=1;i<=6;i++){
scanf("%d",&w[i]);
}
solve();
output();
}
system("pause");
return 0;
}
可以找零时做两次完全背包:(代码)
#include<iostream> //完全背包
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
int cases,euro[10],dp[20000],maxn;
cin>>cases;
while(cases--)
{
for(int i=1;i<=6;++i)
cin>>euro[i];
/*
最多付款的数目(比如人民币中付款49,则可以先付50,找回1,则50称为最多付款的数目)肯定小于
(100/euro[1])*euro[6]+100,因为如果达到这个值,则需要找零至少100/euro[1]=100才能回到[1,100]的范围,这样还不如直接用euro[1]来付款
*/
maxn=(100/euro[1])*euro[6]+100; //上界
fill(dp,dp+maxn,-1);
dp[0]=0;
/*
1. 考虑每种币值可以进行"加"运算
(这是传统的完全背包问题)
dp[i][j]=min{dp[i-1][j],dp[i][j-euro[i]]+1}, i=1~6, j∈[0,maxn]
case1: 没有付出euro[i] || case2: 考虑“再”付出 一个euro[i]
*/
for(int i=1;i<=6;++i) // 加运算
{
for(int j=euro[i];j<=maxn;++j)
if(dp[j-euro[i]]!=-1)
{
if(dp[j]==-1)
dp[j]=dp[j-euro[i]]+1;
else
dp[j]=min(dp[j],dp[j-euro[i]]+1);
}
}
/*
2. 考虑每种币值可以进行"减"运算
(这是一个小扩展——“可以找零 ”)
dp[i][j]=min{dp[i-1][j],dp[i][j+euro[i]]+1}, i=1~6, j∈[0,maxn]
case1: 没有找回euro[i] || case2: 考虑“再”找回 一个euro[i]
注意:因为dp[i][j+euro[i]]中j+euro[i]>j,导致这里要用逆序循环。所以不能死记硬背“0-1背包”用逆序循环,最好自己想一想(脑海里形成一幅二维图像)
*/
for(int i=1;i<=6;++i) // 减运算
{
for(int j=maxn-euro[i];j>0;--j) //因为是减,所以要逆序循环
if(dp[j+euro[i]]!=-1)
{
if(dp[j]==-1)
dp[j]=dp[j+euro[i]]+1;
else
dp[j]=min(dp[j],dp[j+euro[i]]+1);
}
}
double ave=0;
for(int i=1;i<=100;++i)
ave+=dp[i];
printf("%.2f %d\n",ave/100,*max_element(dp+1,dp+101));
}
return 0;
}
分享到:
相关推荐
【标题】"POJ2002-Squares"是一个经典的计算机编程题目,源自北京大学的在线判题系统(POJ,即PKU Online Judge)。这个题目主要涉及到算法设计和实现,尤其是数学和动态规划方面的知识。 【描述】"解题报告+AC代码...
标题“POJ3253-POJ3253-Fence Repair【STL优先队列】”指的是一个在线编程竞赛题目,源自北京大学的在线判题系统POJ(Problem Online Judge)。该题目要求参赛者使用C++编程语言解决特定的问题,并且在解决方案中...
【标题】"POJ1426-Find The Multiple【BFS+同余模】"是一道来源于北京大学在线编程平台POJ的算法题目,主要涉及到了广度优先搜索(BFS)与同余模运算的知识点。这道题目要求解决的是寻找一个整数的倍数问题,可能...
在给出的文件列表中,“POJ1014-Dividing【多重背包+二进制优化】.cpp”和“POJ1014-Dividing【DFS】.cpp”很可能是两份不同的C++代码实现,分别展示了如何结合多重背包和二进制优化以及如何利用DFS来解决问题。...
【标题】"POJ1015-Jury Compromise" 是一个编程竞赛题目,主要涉及的是动态规划(Dynamic Programming, 简称DP)的算法应用。动态规划是一种解决复杂问题的有效方法,它通过将问题分解成子问题,并存储子问题的解来...
【标题】"POJ3020-Antenna Placement"是一个经典的计算机编程竞赛题目,源自北京大学的在线评测系统POJ(PKU Online Judge)。这个题目挑战了参赛者在算法设计和实现上的能力。 【描述】"解题报告+AC代码"意味着这...
《POJ 1000 - 2000 部分题目 官方分类》 编程竞赛,特别是在线判题系统(如POJ,即Problem Online Judge)中的题目,是提升编程技能和算法理解的重要途径。POJ 1000 - 2000 是一个涵盖广泛的题目区间,包含了大量的...
这是魔兽世界终极版POJ的-测试数据,找了好久才找到的。 本来想设置为0积分,但是它居然自动收费(o_ _)ノ。 看传送门:https://pan.baidu.com/s/1cCIwW8psGDASu2JdZawG3Q
【标题】"POJ1837-Balance"是一个在线编程竞赛题目,源自著名的编程练习平台POJ(Programming Online Judge)。这个题目旨在测试参赛者的算法设计和实现能力,特别是处理平衡问题的技巧。 【描述】"解题报告+AC代码...
【标题】"POJ1258-Agri-Net【Prim】" 是一个编程竞赛题目,来源于北京大学的在线评测系统POJ(Problem Online Judge)。这个题目主要涉及到图论中的一个重要算法——普里姆(Prim)算法。 【描述】"北大POJ1258-...
【标题】"POJ2299-Ultra-QuickSort"是北京大学在线判题系统POJ上的一道编程题目,其主要涉及的算法是快速排序(Ultra-QuickSort)。快速排序是一种高效的排序算法,由C.A.R. Hoare在1960年提出。它的基本思想是采用...
【标题】"POJ1010-STAMPS"是一个编程题目,来源于北京大学的在线判题系统POJ(Problem Set of Peking University),这是一处训练程序员算法技能和编程能力的平台。该题目旨在考察参赛者对动态规划或贪心算法的理解...
【标题】"POJ3080-Blue Jeans" 是北京大学在线编程平台POJ(Problem Online Judge)上的一道算法竞赛题目。这道题目主要考察的是动态规划和数组处理的能力,是许多编程爱好者和竞赛选手在提升算法技能时会遇到的经典...
标题“POJ3414-Pots”是一个编程竞赛题目,源自北京大学的在线判题系统POJ(Problem Online Judge)。这个题目主要考察的是算法设计和实现能力,通常涉及计算机科学中的数据结构和算法知识。 解题报告是参赛者在...
【标题】"POJ2503-Babelfish"是一个来自北京大学在线判题系统(POJ,Problem Online Judge)的编程题目。该题目要求参赛者编写程序解决特定的算法问题,通过编程语言实现,然后提交代码以供系统自动评测。 【描述】...
《POJ2525-Text Formalization:深入解析TrieTree》 在计算机科学的世界里,算法和数据结构是解决问题的关键。今天我们要探讨的是一个名为"POJ2525-Text Formalization"的问题,它涉及到一种高效的数据结构——Trie...
【标题】"POJ1416 - 撕碎公司" 这道题目来源于北京大学的在线编程平台POJ(Problem Set),编号为1416,名为“Shredding Company”。该题目是一道典型的计算机科学中的算法问题,主要涉及动态规划(Dynamic ...
【标题】"POJ1003-Hangover"是一个编程竞赛题目,源自北京大学的在线判题系统POJ(Problem Online Judge)。这类题目通常要求参赛者编写程序来解决特定的算法问题,以此锻炼和测试编程技能及算法理解能力。 【描述...
【标题】"POJ1201-Intervals" 是北京大学在线编程平台POJ上的一道题目,这道题目主要涉及计算机科学中的算法设计与分析,尤其是数据结构和时间复杂度优化方面的知识。 【描述】"北大POJ1201-Intervals 解题报告+AC...
【标题】"POJ3122-Pie"是一道来自北京大学在线判题系统POJ(Problem Online Judge)的编程题目。这道题目通常被用于训练程序员的数据结构和算法技能,特别是解决数学问题的能力。在编程竞赛或者算法训练中,这类题目...