Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2416817
  • 博文数量: 392
  • 博客积分: 7040
  • 博客等级: 少将
  • 技术积分: 4138
  • 用 户 组: 普通用户
  • 注册时间: 2009-06-17 13:03
个人简介

范德萨发而为

文章分类

全部博文(392)

文章存档

2017年(5)

2016年(19)

2015年(34)

2014年(14)

2013年(47)

2012年(40)

2011年(51)

2010年(137)

2009年(45)

分类:

2010-04-16 10:24:39

找零钱
Submit: 441   Accepted:65
Time Limit: 1000MS  Memory Limit: 65535K
Description
和女朋友外出就餐时,备足零钱是很有必要的。当饭后结账时,服务员没有足够的零钱找给你,怎么办呢?服务员是绝对不会少收钱的,当然,你可以给他一些小费来省去找钱的麻烦。但是,如果你给的消费太多,女朋友会不高兴的。现在轮到你来决策了。

Input
输入的第一行包含一个整数c,表示测试数据的组数。
每组数据的第一行包含一个整数n,分别表示你要付的钱的数目(1<=n<=10000)。
第二行包含一个整数m表示你身上的零钱的数目(1<=m<=100)。
接下来m行,每行包含一个整数:x表示你身上的钱币的面值 (1<=x<=10000)。你身上的钱的价值总和不小于要付的钱。


Output
对每组数据,输出两个整数,分别表示最后付钱的价值和钱币的数量如果相同价值输出最小数量。

Sample Input

1
1400
3
500
1000
2000


Sample Output

1500 2



类似于背包的dp,也可以看作是dp备忘录,将前面算得的最优值存到stat[]数组里,每次要加入新值时,到stat[]数组里遍历,求出加入后的值,如果更优,则更新stat[]中的相应项



#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;

#define MAX_INT 0x7fffffff

typedef struct _stat
{
    int money;
    int cnt;
}ST_STAT;

int cas, n, m, x;
ST_STAT stat[10010];
vector<ST_STAT> v_larger;

/* 在大于n的集合中查找最小值 */
void find_min()
{
    ST_STAT min;
    min.money = MAX_INT;
    min.cnt = MAX_INT;

    vector<ST_STAT>::iterator beg, end;
    end = v_larger.end();
    for (beg = v_larger.begin() ; beg != end ; beg++)
    {
        if (beg->money < min.money)
            min = *beg;
        else if (beg->money == min.money)
        {
            if (beg->cnt < min.cnt)
            {
                min = *beg;
            }
        }
    }

    printf("%d %d\n", min.money, min.cnt);
    
}

void dp(int size)
{
    int i, j, k, idx;
    ST_STAT temp;

    for (i=0 ; i<size ; i++)
    {
        scanf("%d", &x);
        /* 从后向前寻找最优值,如果从前往后的话,更新的值会覆盖原值(背包中也用过类似的思路) */
        for (j=n-1 ; j>=0 ; j--)
        {
            if (-1 == stat[j].money)
                continue;

            idx = x + stat[j].money;
            /* 钱数已经超过n,将其加入到vector中,等待后面在v中寻找最优值 */
            if (idx >= n)
            {
                temp.money = idx;
                temp.cnt = stat[j].cnt + 1;
                v_larger.push_back(temp);
                continue;
            }

            /* 这个钱数以前已经出现过,看是否需要更新 */
            if (-1 != stat[idx].money)
            {
                if (stat[j].cnt + 1 < stat[idx].cnt)
                {
                    stat[idx].cnt = stat[j].cnt + 1;
                }
            }
           
            /* 这个值没有出现过,直接更新 */
            else
            {
                stat[idx].money = idx;
                stat[idx].cnt = stat[j].cnt + 1;
            }
        }
        /*
        printf("stat:");
        for (k=0 ; k         {
            printf("%d %d, ", stat[k].money, stat[k].cnt);
        }
        printf("\n");
        */

       
    }

    find_min();
}

int main(int argc, char *argv[])
{
    int i;

    scanf("%d", &cas);
    while (cas--)
    {
        scanf("%d", &n);
        scanf("%d", &m);
        memset(stat, 0, sizeof(stat));
        v_larger.clear();
        for (i=1 ; i<=n ; i++)
            stat[i].money = -1;
        stat[0].money = stat[0].cnt = 0;
       
        dp(m);
    }
}


阅读(891) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~