UVa 165 - Stamps 深搜

/**
 * 两个深搜!   下述的币值和面值是不一样的,币值是总的价值,面值是一张的价值。
 * 一个是总的深搜,或者说就是枚举选取哪几种面值可以使得答案最大。
 * 还一个是深搜来判断是否用当前已选择的面值在h(张数)的限制下能够获得当前币值。
 * 其实,关键在于选择,比如,遇到一个面值,分为选择它或者不选择它,以此进行深搜,
 * 判断的时候也是如此, Choose or not!
 *
 * 反省下:
 *     惭愧啊! 学了那么久C,懂得思想,却一直忽略!
 * 面向过程的C,把功能划分各模块各函数解决。。。
 * 就说本题:其中的判断函数judge() 开始的时候,我是都在dfs一个函数都写
 * 一大坨的看了恶心不说,还不能够实现,因为判断的时候也是需要深搜的。
 * 看了人家的代码才理解,与其说看人家代码,还不如说直接copy了。。
 */


#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define MIN 0
using namespace std;
int maxMoney, ans[10], have[10];
int h, k, w;

bool judge(int tar, int th, int num, int th_end, int cur) {
    if(cur == tar)  return true;
    if(th == th_end || num == h) return false;
    if(judge(tar, th + 1, num, th_end, cur)) return true;  //not choose
    if(judge(tar, th, num + 1, th_end, cur + have[th]))  return true; // choose
    return false;
}


/** available 是已经能够得到的币值,th_end是用数组hava记录的已选取的面值。*/
void dfs(int available, int th_end) {

    /** 递归的最后判断是否能够更新当前答案. */
    if(available - 1> maxMoney) {
        maxMoney = available - 1;
        memcpy(ans, have, sizeof(have));
    }

    if(judge(available, 0, 0, th_end, 0))
        dfs(available + 1, th_end);      //不把当前面值 available 放入已取面值里
    if(th_end < k) {
        have[th_end++] = available;
        dfs(available + 1, th_end);      //把当前面值 available 放入已取面值里,此时th_end 已加一
        th_end --;
        have[th_end] = -1;
    }


}

int main()
{
    freopen("in.txt", "r", stdin);
    while(scanf("%d%d", &h, &k), h && k) {
        maxMoney = MIN;
        dfs(0, 0);
        memset(have, false, sizeof(have));
        for(int i = 0; i < k; i ++) {
            printf("%3d", ans[i]);
        } printf(" ->");
        printf("%3d\n", maxMoney);
    }
    return 0;
}

 

你可能感兴趣的:(UVa 165 - Stamps 深搜)