B. Quasi Binary
题目
题意 给一个数 ,将其分解成一些只有1和0组成的数字和,输出最小个数和这样的数字。
扯淡
暴力其实就能过,主要练习一下dp和这种初始化的方式
思路
dp,定义其为凑出数字i 所需的最小数量。同时定义一个pre 记录前驱状态。
AC代码
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
//#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 1e6 + 10;
vector<int> ans, v;
void init()
{
// 每次插入尾部是1 or 0的数字 搜索过程类似bfs
//用队列十分优雅的 取到所有待选数字
queue<int> q;
q.push(1);
while (q.size())
{
int t = q.front();
q.pop();
v.push_back(t);
int k = t * 10 + 1;
if (k < N)
q.push(k), q.push(k - 1);
}
}
void solve()
{
init();
int n;
cin >> n;
//初始化dp 一遍求最小初始化为正无穷 求最大初始化为负无穷
vector<int> dp(n + 1, inf), pre(n + 1, 0);
dp[0]=0;//规定 0合法
for (int i = 1; i <= n; i++)//和完全背包dp的定义不同 必须要凑满n
for (auto x : v)
if (i - x >= 0 && dp[i - x] + 1 < dp[i])
dp[i] = dp[i - x] + 1, pre[i] = i - x;//记录该状态的前状态
int k = n;
while (k)
{
int s = k - pre[k];//得到该状态的选择
ans.push_back(s);
k = pre[k];//更新k为上一状态 pre指向其前状态
}
cout << dp[n] << endl;
for (auto a : ans)
cout << a << ' ';
}
int main()
{
ios::sync_with_stdio();
solve();
return 0;
}