【解题报告】饭卡

解题报告——饭卡

  • 问题描述   

Time Limit: 1000ms

Memory Limit: 32768KB

64-bit integer IO format: %I64d      Java class name: Main

电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)。所以大家都希望尽量使卡上的余额最少。

某天,食堂中有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。

Input

多组数据。对于每组数据:
第一行为正整数n,表示菜的数量。n<=1000。
第二行包括n个正整数,表示每种菜的价格。价格不超过50。
第三行包括一个正整数m,表示卡上的余额。m<=1000。

n=0表示数据结束。

Output

对于每组输入,输出一行,包含一个整数,表示卡上可能的最小余额。

Sample Input

1
50
5
10
1 2 3 2 1 1 2 3 2 1
50
0

Sample Output

-45
32
  • 解题思路

动态规划问题。解题的时候参考了01背包问题以及其延伸的小偷入户抢劫的问题,对于每一道菜都可以选择买或者不买,可以标记在选择购买这道菜之前能够到达的余额值,每次选择买或不买之后刷新能够达到的余额值,最后答案可以检索最小能够达到的余额值得到。

其中为了保证余额最小,要保证价格贵的较后购买,所以要先对菜的价钱进行从小到大排序。

并且为了使用数组进行标记,即要考虑余额为负的标记问题,把所有余额加上50进行标记,输出时用所求得答案减去50输出。

  • 错误代码

  最开始没有理解动态规划的含义,只是照着动态规划的感觉照葫芦画瓢还画错了。对于每一道菜都进行了选择并标记,事实上相当于从最便宜从最贵能买的都买了,并没有动态规划的状态转移过程。

  错误代码如下:

 1 //错的相当离谱的代码
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 int main()
 6 {
 7     int n,m,i,x;
 8     while (1){
 9         scanf("%d",&n);
10         if (n==0) break;
11         int meal[n];
12         for (i=0;i<n;i++) scanf("%d",&meal[i]);
13         sort(meal,meal+n);
14         scanf("%d",&m);
15         x=m;
16         i=0;
17         int s[m+50];
18         for (i=0;i<m+49;i++) s[i]=0;
19         s[m+50]=1;
20         for (i=0;i<n;i++){
21             if (x>=5) {
22                 s[x+50-meal[i]]=1;//没有状态转移的过程,将每一道菜都选择了。
23                 x=x-meal[i];
24             }
25         }
26         for (i=0;i<m+50;i++)
27             if (s[i]==1){
28                 printf("%d\n",i-50);
29                 break;
30             }
31     }
32     return 0;
33 }
  • AC代码

   又看了看关于动态规划问题,重点学习了一下01背包问题延伸的小偷入户抢劫问题,找到了这道题的转移方程,即

1     for (i=0;i<n;i++){
2         for (j=55;j<=m+50;j++){
3             if (s[j]==1){
4                 s[j-meal[i]]=1;
5             }
6         }
7     }

  利用上一次能达到的所有余额值来更新选择了这道菜后能达到的余额值,这样再选择所有能达到余额值的最小值就能得到答案。

   AC代码如下:

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 int main()
 5 {
 6     int n,m,i,j,x,ans;
 7     while (1){
 8         scanf("%d",&n);
 9         if (n==0) break;
10         int meal[n];
11         for (i=0;i<n;i++) scanf("%d",&meal[i]);
12         sort(meal,meal+n);
13         scanf("%d",&m);
14         x=m;
15         i=0;
16         int s[m+51];
17         for (i=0;i<=m+49;i++) s[i]=0;
18         s[m+50]=1;
19         ans=m+50;
20         for (i=0;i<n;i++){
21             for (j=55;j<=m+50;j++){
22                 if (s[j]==1){
23                     s[j-meal[i]]=1;
24                     ans=min(ans,j-meal[i]);
25                 }
26             }
27         }
28         printf("%d\n",ans-50);
29     }
30     return 0;
31 }

题是简单题,但架不住我菜啊(。)

原文地址:https://www.cnblogs.com/sixwater6H2O/p/11241241.html

时间: 2024-07-30 19:36:08

【解题报告】饭卡的相关文章

题解报告:hdu 2546 饭卡(01背包)

Problem Description 电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额.如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够).所以大家都希望尽量使卡上的余额最少.某天,食堂中有n种菜出售,每种菜可购买一次.已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少. Input 多组数据.对于每组数据:第一行为正整数n,表示菜的数量.n<=1000.第二行包括n个正整数,表示每种菜的价格.价

HDU 2546 饭卡 (01背包)

饭卡 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 14877    Accepted Submission(s): 5150 Problem Description 电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额.如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法

洛谷OJ P1379 八数码难题 解题报告

洛谷OJ P1379 八数码难题 解题报告 by MedalPluS 题目描述   在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变.   输入格式   输入初试状态,一行九个数字,空格用0表示   输出格式 只有一行,该行只有一个数字,表示从初始状态到

常州培训 day3 解题报告

第一题: 给出数轴正半轴上N个点的坐标和其权值,给出初始体力值M,人一开始在位置0,体力值会随着走过路程的增加而增加,走多少个单位的路消耗多少体力值.到每个点可以打掉,消耗的体力值就是其权值.求 最多能打掉多少点. N<=10000,其他<=10^18; 解题过程: 1.一开始就直接想到是贪心,首先人是不可能往左走的,否则不会最优.枚举最后停在哪个点,减去到这个点需要的体力,然后把这个点之前的所有点(包括这个店)的权值排个序,从小到大一个一个打,打到体力没有为止.复杂度分析:枚举N次,每次快拍

解题报告 之 2015蓝桥杯 垒骰子

解题报告 之 2015蓝桥杯 垒骰子 赌圣 atm 晚年迷恋上了垒骰子,就是把骰子一个垒在还有一个上边.不能歪歪扭扭,要垒成方柱体. 经过长期观察,atm 发现了稳定骰子的奥秘:有些数字的面贴着会互相排斥! 我们先来规范一下骰子:1 的对面是 4.2 的对面是 5,3 的对面是 6. 如果有 m 组相互排斥现象,每组中的那两个数字的面紧贴在一起,骰子就不能稳定的垒起来. atm 想计算一下有多少种不同的可能的垒骰子方式. 两种垒骰子方式同样,当且仅当这两种方式中相应高度的骰子的相应数字的朝向都同

HDUOJ 2546 饭卡

饭卡 Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 254664-bit integer IO format: %I64d      Java class name: Main 电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额.如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够

杭电 2546 饭卡【01背包】

解题思路:先忽略饭卡余额大于等于5块才能买饭这一细节,需要求的是饭卡里面剩余的钱最少,转化一下,变成花的钱最多,那么剩下的钱就最少,再考虑余额大于等于5块才能买饭这一细节,可以这样想,如果卡里的余额不足5块,那么买不到饭,直接输出现在卡里的金额,如果卡里的钱多于5块,我们就可以先将这5块钱留起来,这样保证它每一次买饭卡里的余额都是大于5块的,最后卡里剩下的5块钱则用来买最贵的菜,这样就需要对菜的价钱进行排序.经过这样的转化后就可以转化成一个容量为m-5的包怎样装获得最大价值的01背包问题了. 反

NOIP2004 解题报告

第一题:津津的零花钱一直都是自己管理.每个月的月初妈妈给津津300元钱,津津会预算这个月的花销,并且总能做到实际花销和预算的相同. 为了让津津学习如何储蓄,妈妈提出,津津可以随时把整百的钱存在她那里,到了年末她会加上20%还给津津.因此津津制定了一个储蓄计划:每个月的月初,在得到妈妈给的零花钱后,如果她预计到这个月的月末手中还会有多于100元或恰好100元,她就会把整百的钱存在妈妈那里,剩余的钱留在自己手中. 例如11月初津津手中还有83元,妈妈给了津津300元.津津预计11月的花销是180元,

NOIP2009解题报告

09年的题总体来说 没有难题,但是每道题除了第一题都要认真的慢慢写才能AC, 第一题: R国和S国正陷入战火之中,双方都互派间谍,潜入对方内部,伺机行动. 历经艰险后,潜伏于S国的R国间谍小C终于摸清了S国军用密码的编码规则:1. S国军方内部欲发送的原信息经过加密后在网络上发送,原信息的内容与加密后所的内容均由大写字母‘A’—‘Z’构成(无空格等其他字母).2. S国对于每个字母规定了对应的“密字”.加密的过程就是将原信息中的所有字母替换为其对应的“密字”.3. 每个字母只对应一个唯一的“密字