码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 1010 STAMPS

时间:2015-02-01 21:46:16      阅读:200      评论:0      收藏:0      [点我收藏+]

标签:

http://poj.org/problem?id=1010

 

题意:

一: 给定多种类型邮票的面值(不同类型邮票的面值可以相同)

二: 给出客户所需的总面值,求不超过4张邮票的总面值为所给面值的最佳购买方案

最佳方案的定义为: ①种类最多 ②张数最少 ③单张面值最大

若最佳方案多于一个则输出tie

若不存在满足需求的方案,输出none

否则,输出最佳方案

 

解法:

dfs

主要的几点剪枝:

①每种方案邮票数都不超过4,考虑上tie的情况,则每种面值的邮票只保留5种就够了

②DFS深度不超过4

③邮票按面值升序排序,DFS到面值k时,不再搜索面值<k的邮票

 

代码:  16MS  352K

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

#define N 25

struct Node {
    int typ, num, mx, amo[N];  //种类数,张数,最大面值,各种类数量
} p, t;
int a[N], x, n, ans;

void dfs(int num, int val, int crt) {  //当前数量,当前总面值,第crt种
    if (val == x) {  //符合条件
        t.typ = t.mx = 0;
        t.num = num;
        for (int i = 0; i < n; ++i) {  //计算数据
            if (t.amo[i]) {
                ++t.typ;
                if (t.mx < a[i]) {
                    t.mx = a[i];
                }
            }
        }
        if (t.typ > p.typ || t.typ == p.typ && t.num < p.num || t.typ == p.typ && t.num == p.num && t.mx > p.mx) {
            ans = 1;  //得到更佳方案
            p = t;
        }
        else if (t.typ == p.typ && t.num == p.num && t.mx == p.mx) {
            ++ans;  //方案相同
        }
        return;
    }
    for (int i = 0; i < 5; ++i) {  //枚举当前种邮票的张数
        if (num + i <= 4 && val + i * a[crt] <= x && crt < n) {  //剪枝
            t.amo[crt] += i;
            dfs(num + i, val + i * a[crt], crt + 1);
            t.amo[crt] -= i;
        }
    }
}

int main() {
    while (~scanf("%d", &x) && x) {
        for (a[n = 0] = x, n++;;) {
            scanf("%d", &x);
            if (!x) {
                break;
            }
            int cnt = 0;
            for (int i = 0; i < n; ++i) {
                if (a[i] == x) {
                    ++cnt;
                }
            }
            if (cnt < 5) {  //同面值保留5种
                a[n++] = x;
            }
        }
        sort(a, a + n);  //按面值从小到大排序
        while (~scanf("%d", &x) && x) {
            ans = 0;
            memset(&t, 0, sizeof(t));
            memset(&p, 0, sizeof(p));
            dfs(0, 0, 0);
            printf("%d ", x);
            if (!ans) {  //没有方案
                printf("---- none\n");
            }
            else if (ans > 1) {  //多于一个最佳方案
                printf("(%d): tie\n", p.typ);
            }
            else {
                printf("(%d):", p.typ);
                for (int i = 0; i < n; ++i) {
                    if (p.amo[i]) {
                        for (int j = 0; j < p.amo[i]; ++j) {
                            printf(" %d", a[i]);
                        }
                    }
                }
                printf("\n");
            }
        }
    }
    return 0;
}

 

POJ 1010 STAMPS

标签:

原文地址:http://www.cnblogs.com/rsola/p/4266061.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!