CF538B题解
what_can_I_do · · 题解
传送门
这道题一眼 dp。
这一题感觉跟这一题有点像。我们可以先预处理出所有只包含
接下来想怎么样实现输出构造方案。可以用一个 vector<int> pe[1000010] 来实现。其中每个 pe[i]=pe[i-v[j]] 就行了。
现在我们要稍微改一下状态转移方程。我们要把 dp_i=min(dp_i,dp_{i-v_j}+1) 改成 if(dp[i]>dp[i-v[j]]+1) 接下来再跟上 dp[i]=dp[i-v[j]]+1;,然后再将方案转移,pe[i]=pe[i-v[j]],最后在后面放入新的选择 pe[i].push_back(v[j]) 就行了。
还有,预处理就不用我讲了吧,直接模拟。
CODE:
#include<bits/stdc++.h>
using namespace std;
int n,v[200],l=0,dp[1000010]={0};
vector<int> pe[1000010];
int main()
{
scanf("%d",&n);
for(register int now=0;now<=n;)
{
v[l]=now,l++;
now++;
int s=1;
while((now%(int(pow(10,s))))/(int(pow(10,s-1)))==2) s++,now=now-2*int(pow(10,s-2)),now+=int(pow(10,s-1));
}
l--;
for(register int i=1;i<=n;i++) dp[i]=999999999;
for(register int i=0;i<=n;i++)
for(register int j=0;j<=l;j++)
if(i>=v[j])
if(dp[i]>dp[i-v[j]]+1)
{
dp[i]=dp[i-v[j]]+1;
pe[i]=pe[i-v[j]];
pe[i].push_back(v[j]);
}
printf("%d\n",dp[n]);
for(register int i=0;i<=pe[n].size()-1;i++) printf("%d ",pe[n][i]);
return 0;
}