[AT_abc118_d]题解
思路分析:
这是一道恰好装满的完全背包问题,和正常的完全背包一样,初始化改一下即可。
这里说一下为什么 \(dp[0]\) 要赋成 \(0\) 而 \(dp[1]\) 到 \(dp[n]\) 要赋值成一个极小值,因为只有 \(0\) 在背包容量恰好为 \(0\) 的时候价值为 \(0\),要求最大值所以剩下的要赋成一个极小值。
然后就是一道完全背包模板题了,这道题时间复杂度应该是趋近于 \(O(nm^2)\),因为 \(m\) 很小所以几乎可以做到 \(O(n)\),那就可以用不加优化的 \(3\) 层循环来做。
代码:
#include<bits/stdc++.h>
using namespace std;
int read(){
char ch=getchar();
int x=0;
bool flag=false;
while(ch<'0'||ch>'9'){
if(ch=='-'){
flag=true;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+(ch-'0');
ch=getchar();
}
return flag?-x:x;
}//快读
bool cmp(int x,int y){
return x>y;
}
int n,m,dp[10003],a[15],num[15]={6,2,5,5,4,5,6,3,7,6};//我的m和n与题目中颠倒的
signed main(){
m=read(),n=read();
//再说一下,我的m和n与题目中是颠倒的
for(int i=1;i<=n;i++){
a[i]=read();
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=m;i++){
dp[i]=-0x3f3f3f3f;
}
//初始化
for(int i=1;i<=n;i++){
for(int j=2;j<=m;j++){
int tmp=10,cnt=a[i];
for(int k=1;j-k*num[a[i]]>=0;k++){
if(dp[j-k*num[a[i]]]>=0){
dp[j]=max(dp[j],dp[j-k*num[a[i]]]*tmp+cnt);//状态转移
}
cnt=cnt*10+a[i];
tmp*=10;
}
}
}
cout<<dp[m];//输出答案
return 0;
}
本文来自博客园的一名初中生蒟蒻OIer,作者:xxxalq,如需转载请注明原文链接:https://www.cnblogs.com/xxxalq/articles/17840040.html
并将作者 xxxalq 标注在醒目位置。
浙公网安备 33010602011771号