PAT.Advanced.P1068

来源:互联网 发布:对网络攻防技术的认识 编辑:程序博客网 时间:2024/06/05 00:23

------>   原题链接    <-------

题意大概是有1w个硬币,店家只要精确数额(不多收也不找零)问能否凑出给出的数额。

做法就是暴力循环 + 剪枝优化

不剪枝的话有一个点是过不去的。

1、剔除所有大于给定数量的硬币,

2、对于重复的硬币,如果第一个不行,那么排除掉后面所有的重复硬币的可能性。(见注释的核心剪枝行)

#include <iostream>#include <cstdio>#include <vector>#include <algorithm>int amount;int n;int coins[10000];using namespace std;vector<int> path;int compare_ints(const void* a, const void* b)   // comparison function{    int arg1 = *reinterpret_cast<const int*>(a);    int arg2 = *reinterpret_cast<const int*>(b);    if(arg1 < arg2) return -1;    if(arg1 > arg2) return 1;    return 0;}bool find(int start, int target){    for (int i = start; i < n; i++)    {        if(coins[i] > target){            return false;        }        if(coins[i] == target) {            path.push_back(i);            return true;        }        if(coins[i] < target){            path.push_back(i);            if(find(i + 1, target - coins[i])) return true;            else path.pop_back();            while(i < n && coins[i] == coins[i+1]) i++; //这一句是核心的剪枝,如果没有这一行最后一个case就会超时。        }    }    return false;}int main(){int tmp;int cnt = 0;scanf ("%d %d", &n, &amount);for (int i = 0; i < n; i++) {scanf ("%d", &tmp);if(tmp <= amount) coins[cnt++] = tmp;}n = cnt;qsort(coins, n, sizeof(int), compare_ints);    if(find(0, amount)){        printf("%d",coins[path[0]]);        for (int i = 1; i < path.size(); i++)        {        printf(" %d", coins[path[i]]);        }    }else printf("No Solution\n");}


0 0
原创粉丝点击