问题 C: Canonical Coin Systems
A coin system S is a finite (nonempty) set of distinct positive integers corresponding to coin values, also called denominations, in a real or imagined monetary system. For example, the coin system in common use in Canada is {1, 5, 10, 25, 100, 200}, where 1 corresponds to a 1-cent coin and 200 corresponds to a 200-cent (2-dollar) coin. For any coin system S, we assume that there is an unlimited supply of coins of each denomination, and we also assume that S contains 1,since this guarantees that any positive integer can be written as a sum of (possibly repeated) values in S.
Cashiers all over the world face (and solve) the following problem: For a given coin system and a positive integer amount owed to a customer, what is the smallest number of coins required to dispense exactly that amount? For example, suppose a cashier in Canada owes a customer 83 cents. One possible solution is 25+25+10+10+10+1+1+1, i.e.,8 coins, but this is not optimal, since the cashier could instead dispense 25 + 25 + 25 + 5 + 1 + 1 + 1, i.e., 7 coins (which is optimal in this case). Fortunately, the Canadian coin system has the nice property that the greedy algorithm always yields an optimal solution, as do the coin systems used in most countries. The greedy algorithm involves repeatedly choosing a coin of the
largest denomination that is less than or equal to the amount still owed, until the amount owed reaches zero. A coin system for which the greedy algorithm is always optimal is called canonical.
Your challenge is this: Given a coin system S = {c1, c2, . . . , cn }, determine whether S is canonical or non-canonical. Note that if S is non-canonical then there exists at least one counterexample, i.e., a positive integer x such that the minimum number of coins required to dispense exactly x is less than the number of coins used by the greedy algorithm. An example of a non-canonical coin system is {1, 3, 4}, for which 6 is a counterexample, since the greedy algorithm yields 4 + 1 + 1 (3 coins), but an optimal solution is 3 + 3 (2 coins). A useful fact (due to Dexter Kozen and Shmuel Zaks) is that if S is non-canonical, then the smallest counterexample is less than the sum of the two largest denominations.
输入
Input consists of a single case. The first line contains an integer n (2 ≤ n ≤ 100), the number of denominations in the coin system. The next line contains the n denominations as space-separated integers c1 c2 . . . cn, where c1 = 1 and c1 < c2 < . . . < cn ≤ 10^6
输出
Output “canonical” if the coin system is canonical, or “non-canonical” if the coin system is non-canonical.
样例输入
复制样例数据
4
1 2 4 8
样例输出
canonical
题意就是凑一个钱数,每次选用<=这个钱数里最大的数凑成的这个数,所用的钱的个数是否是最少的
比赛时应该是脑子短路了,以前做凑钱数的题不是贪心就是dp,这次其实就是把贪心和dp联系起来,看贪心出来的数是不是正确的最小的,也就是贪心算出来的数是不是dp算出来的数。
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn=2e6+5;
int a[maxn];
int dp[maxn];
int getmax[maxn];
int n;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
memset(dp,INF,sizeof dp);
dp[0]=0;
for(int i=1;i<=n;i++)// 完全背包求钱的数目
{
for(int j=0;j<=maxn;j++)
{
if (j>=a[i])
dp[j]=min(dp[j],dp[j-a[i]]+1);
}
}
for(int i=0;i<=maxn;i++)//贪心求钱的数目
{
for(int j=1;j<=n;j++)
{
if(i>=a[j])
getmax[i]=getmax[i-a[j]]+1;
}
}
bool flag=true;
for(int i=0;i<maxn;i++)
{
if(getmax[i]!=dp[i])//两种不相同,贪心出来的不是最少的
{
flag=false;
break;
}
}
if(flag)
printf("canonical\n");
else
printf("non-canonical\n");
}