AtCoder ABC 251
D - At Most 3 (Contestant ver.)(构造 + 思维)
Description:
构造一个长度为300的序列 任取1或者2或者3个数 使其能构成1~1e6的所有数
Solution:
将1e6想办法分为三分 如果是想着/3的话 那就走上了歪路
应该想的是 将六位数分割成六位 一个数可以影响两位
三个数相加就可以影响6位了 于是构造方案出现
Code:
signed main()
{
int w;
cin >> w;
cout << 300 << endl;
for(int i = 1; i <= 300; i ++)
cout << i << ' ' << i * 100 << ' ' << i * 10000 << ' ';
}
E - Takahashi and Animals(状态DP)
Description:
有一个序列 长度为n a_i代表其代价 若选择了i 那么i和**(i + 1) % n**将被点亮 并花费a_i
求点亮所有位置的最小花费
Solution:
很经典的一种状态设计和转移的模型
我们可以简单的想到 设计**dp[i] [2]**为当前位置选和不选两种状态
那么转移就可以设置为
dp[i][0] = dp[i - 1][1];
dp[i][1] = min(dp[i - 1][1], dp[i - 1][0]) + a[i];
写到这里 貌似已经结束了 但其实还有问题 我们忘记考虑了点亮n和1之间的关系
这点要是在转移方程里写应该会很麻烦 于是我们直接分类讨论
Code:
//一种是必选1
f[2][1] = a[1] + a[2];
f[2][0] = a[1];
rep(i, 3, n + 1)
{
f[i][0] = f[i - 1][1];
f[i][1] = min(f[i - 1][1], f[i - 1][0]) + a[i];
}
int res1 = min(f[n][1], f[n][0]);
//一种是不确定选不选1
f[2][1] = a[2];
f[2][0] = a[2];
rep(i, 3, n + 2)
{
f[i][0] = f[i - 1][1];
if(i == n + 1)
f[i][1] = min(f[i - 1][1], f[i - 1][0]) + a[1];
else
f[i][1] = min(f[i - 1][1], f[i - 1][0]) + a[i];
}
int res2 = min(f[n + 1][1], f[n + 1][0]);
cout << min(res1, res2);