题目描述
奶牛手上有N枚硬币,第i枚硬币的面值是d[i]元。无人售货机有1000件礼物,编号从1至1000,第i件礼物需要i元,售货机不设找赎。奶牛想知道:利用这N枚硬币,哪些礼物是不可能买得到的?(如果奶牛无法凑出沅元,即不可能买到第i件礼物;如果能凑出沅元,那就有可能买第件礼物)。从小到大输出不可能买得到的礼物的编号。
输入格式
第一行,一个整数N,1<=N<=40。第二行,N个整数,第i个整数是d[i],1<=d[i]<=100。
输出格式
一行,从小到大输出不可能买得到的礼物的编号。
输入/输出样例1
输入:
3
2 3 6
输出:
1 4 7 10 12 13 14 ......1000
分析
1.问题:是求若干硬币任意组合后,能表示哪些面值;
结论:以每个硬币为阶段。
2.状态:dp[i][j]表示用第i个硬币组合时,能否表示面值j;
3.状态转移方程:
dp[i][j]=dp[i-1][j] //不用第i个硬币
dp[i][j]=1 (j>=a[i] &&dp[i-1][j-a[i]==1) //用第i个硬币
(1<=i<=n , 0<=j<=1000)
4.问题的解:
dp[n][j]==0
5. 该算法的时间复杂度为O(n*1000)。
代码
#include<bits/stdc++.h>
using namespace std;
int n;
int a[1000000+10],dp[1000+10][1000+10];
int main(){
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
dp[0][0]=1;//初始化
for(int i=1;i<=n;i++)
{
for(int j=0;j<=1000;j++)
{
dp[i][j]=dp[i-1][j];
if(j>=a[i]&&dp[i-1][j-a[i]]==1)dp[i][j]=1;
}
}
for(int j=0;j<=1000;j++)
{
if(dp[n][j]==0)cout<<j<<" ";
}
return 0;
}