(动态规划)
思路:存在最优方案,之中每一个数要么是1,要么是Bi,(猜想的结论,不会证明)
dp[n][2]
dp[i][j] 表示第 i 个数结尾,第 i 个数为1(j = 1) or 第 i 个数为 Bi 时的最大可爱值。
当前的状态是由前两个状态转移得到(分别为前一个状态取1,或取 Bi)
当前的状态还有两种(分别为前一个状态取1,或取 Bi)
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int f[N][2];
int n, b[N];
int main() {
cin >> n;
for (int i = 1; i <= n ; i ++ ) cin >> b[i];
for (int i = 2; i <= n ; i ++ ) {
f[i][0] = max(f[i - 1][0] + abs(1 - 1), f[i - 1][1] + abs(1 - b[i - 1]));
f[i][1] = max(f[i - 1][0] + abs(b[i] - 1), f[i - 1][1] + abs(b[i] - b[i - 1]));
}
int res = max(f[n][0], f[n][1]);
cout << res << endl;
return 0;
}
(模拟)
直接官方思路:
对于边长为 6 的正方形纸片:显然一个纸片就要一个框,所以答案加 f 。
对于边长为 5 的正方形纸片:显然一个纸片就要一个框,所以答案加 e。
对于边长为 4 的正方形纸片:显然一个纸片就要一个框,所以答案加 d。
对于边长为 3 的正方形纸片:一个框能放 4 个,所以答案加 ceil(c / 4)向上取整。
对于边长为 2 的正方形纸片:
我们可以把他和边长为 4 的放在一起,不难发现在每个框还可以放得下 5 个。
放完了之后可以把他和边长为 3 的放在一起。
如果还有多出来 1 个边长为 3 的,那么就可以放 5 个边长为 2 的。
如果还有多出来 2 个边长为 3 的,那么就可以放 3 个边长为 2 的。
如果还有多出来 3 个边长为 3 的,那么就可以放 1 个边长为 2 的。
如果还有多的,就单独放。
对于边长为 1 的正方形纸片:哪里有空就往哪放,如果还有多的就单独放。
#include <bits/stdc++.h>
using namespace std;
double s, a, b, c, d, e, f;
int t;
int main() {
cin >> t;
while ( t -- ) {
cin >> s;
cin >> a >> b >> c >> d >> e >> f;
int res = 0;
res = f + e + d + ceil(c / 4); // ceil 向上取整
int putb = d * 5; // 放4的框,可以放多少个 2 * 2的
if ((int)c % 4 != 0) {
if ((int)c % 4 == 1) putb += 5; // 一个框里面放1个4 * 4的,剩余空间就可以放5个2 * 2的
if ((int)c % 4 == 2) putb += 3; // 一个框里面放2个4 * 4的,剩余空间就可以放3个2 * 2的
if ((int)c % 4 == 3) putb += 1; // 一个框里面放3个4 * 4的,剩余空间就可以放1个2 * 2的
}
if (b > putb) res += ceil((b - putb) / 9); // 2 * 2的还有剩余
int used = 6 * 6 * f + 5 * 5 * e + 4 * 4 * d + 3 * 3 * c + 2 * 2 * b; // 被使用过的面积和
int puta = res * 6 * 6 - used; // 除a本身以外,其他框中可以放a的总数
if (puta < a) { // 说明除放入其他框的a,a还有剩余,要自己一种的放入框了
res += ceil((a - puta) / 6 * 6);
}
if (res <= s) cout << "Yes" << endl;
else cout << "No" << endl;
}
return 0;
}
(状压dp,优化)
我的评价是好难,还不是很懂,需要再思考思考~
// 这也太难了吧,还得思考思考~
#include <bits/stdc++.h>
using namespace std;
const int mod = 998244353;
int f[1 << 8][1 << 8];
char s[17];
int main() {
int n, m;
cin >> n >> m;
int res = 0;
while ( n -- ) {
cin >> s;
int a = 0;
for (int i = 0; i < m ; i ++ ) {
a = (a << 1) | (s[i] == 'o'); // 将输入的s转化为二进制数,o为1,h为0
}
int x = a >> 8, y = a & 255, tmp = 1; // x为高八位,y为低八位,初始tmp为1,队列为空(不懂)
for (int i = 0; i < (1 << 8) ; i ++ ) { // 这样一来,hi,li都与x,y不同,的方案数,满足题意
if (!(x & i)) {
(tmp += f[i][y]) %= mod;
}
}
(res += tmp) %= mod; // 累加方案数
for (int i = 0; i < (1 << 8) ; i ++ ) { // 更新一下f,阿巴阿巴~
if (!(y & i)) {
(f[x][i] += tmp) %= mod;
}
}
}
cout << res << endl;
return 0;
}
妙啊,简直就是妙蛙种子吃了妙脆角走进了米奇妙妙屋,妙到家了~