题目大致内容就是根据一个货币系统a[1,2,…n],找到一个等价的货币系统b[1,2,3,…m],使得m最小,求m。
对于这道题,聪明人一眼就看出来了解题思路(当然,我显然是不聪明的/(ㄒoㄒ)/~~)。
***具体思路是:***对于货币系统a中的任意一种货币,我们先从小到大排序,如果大的货币可以被所有比它小的货币的表示出来,那么这种货币就可以被去掉。
这样,我们就可以用完全背包来解题。背包容量为所有货币种类中的最大值,也就是排序之后的a[n]。
具体代码如下,我加上了注释,方便小伙伴们理解。
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#define pl printf("\n")
#define pk printf(" ")
#define ll long long int
using namespace std;
void in(int& x) {
int f = 1;
x = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
x *= f;
}
void inl(ll& x) {
int f = 1;
x = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
x *= f;
}
void out(int a) {
if(a < 0) { putchar('-'); a = -a; }
if(a >= 10) out(a / 10);
putchar(a % 10 + '0');
}
void outl(ll a) {
if(a < 0) { putchar('-'); a = -a; }
if(a >= 10) outl(a / 10);
putchar(a % 10 + '0');
}
const int N=107,M=25007;
int a[N];
//这里只需要考虑可不可以装满背包,所以用bool类型就可以啦
bool dp[M];
int main()
{
int k;
in(k);
while(k--){
int n,ans=0;
in(n);
for(int i=1;i<=n;i++)
{
in(a[i]);
}
sort(a+1,a+n+1);
memset(dp,0,sizeof(dp));
//前0种货币肯定可以表示出0货币
dp[0]=1;
for(int i=1;i<=n;i++)
{
/*
这里的判断很关键!!!!!!!
在对a[i]货币进行决策之前,先判断一下此时的dp[a[i]]的状态;
这样我们就可以知道a[i]这种货币是否可以被它之前的货币表示出来.
*/
if(!dp[a[i]])
ans++;
for(int j=a[i];j<=a[n];j++){
dp[j] = dp[j] | dp[j-a[i]];
}
}
out(ans);
pl;
}
return 0;
}
下面我介绍一下我自己比较笨的方法,其实也是证明了为什么只要a[i]这种货币能够被之前的货币表示出来,就舍弃的原因.
首先,我们用数学语言来描述一下这道题目:
对于一个数列a=[a1,a2,..an],我们需要找到内部数据尽可能少的数列b=[b1,b2,...bm]
使得:
对于任意的M
若存在n个整数k1,k2....kn,使得:
k1*a1+k2*a2+...+kn*an=M
则,必存在m个整数l1,l2....lm,同样使得:
l1*b1+l2*b2+....+lm*bm=M
反之,则对于任意的m个整数,l1*b1+l2*b2+....+lm*bm都不可能等于M
所以,从上面的公式我们可以看出,k1a1+k2a2+…+kn*an就是对n个一维列向量组成的向量组a=[a1,a2,…an]进行线性组合.
然后,我们需要找到一个尽可能向量个数少的一维列向量组b,使得,两个列向量组可以相互线性表示,也就是等价.
学过线性代数的同学大概就看出来了,我们想要找的b就是向量组a的极大线性无关组.
根据极大线性无关组的定义,我们只要将a种所有可以被其他向量线性表示的向量去掉,剩下的就是a的极大线性无关组啦!!.
而我们完全背包的过程,就是不断去掉那些可以被其他向量线性表示的向量.
(现代的知识点本人有点模糊了,如果推导过程有错误,欢迎小伙伴们留言指出.O(∩_∩)O)