具体内容有人想看请留言,我再补充
无关细节
- 使用
ios::sync_with_stdio(false);
解除c++流和stdin
&stdout
的绑定。使用cin.tie(nullptr);
解除cin
和cout
的绑定。通过如上操作可以提高读写的速度,且速度略快于scanf
和printf
,但略慢于快读快写。解绑之后就尽量不要再与scanf
和printf
混用,以免出错。此外,当题目存在大量输出的时候不要使用endl
。
有些人会见到cout.tie(0)
的写法,但是这是没有意义的。因为cout
默认不与任何流对象相关联。 - 不要迷信y总的dp分析法,把状态转移数组视作集合没有明显的好处,不如就把状态转移数组认为是到某个状态的属性。分析状态转移方程的关键还是在于搞清楚当前状态是什么和其他状态如何转移到当前状态。
其他
洛谷P1544和这道题相似,可以去做一下巩固。
AC代码
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int MOD = 1e9 + 7;
int f[55][55][15][15]; // f[i][j][cnt][v] 在(i,j)处,有cnt个宝贝,最大价值是v的全部方案数
int c[55][55];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m, k;
cin >> n >> m >> k;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
cin >> c[i][j];
c[i][j]++;
}
}
f[0][1][0][0] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
f[i][j][0][0] = (f[i][j][0][0] + f[i - 1][j][0][0]) % MOD;
f[i][j][0][0] = (f[i][j][0][0] + f[i][j - 1][0][0]) % MOD;
for (int cnt = 1; cnt <= k; ++cnt) {
int& take_state = f[i][j][cnt][c[i][j]];
for (int v = 0; v <= 13; ++v) {
if (v < c[i][j]) {
take_state = (take_state + f[i - 1][j][cnt - 1][v]) % MOD;
take_state = (take_state + f[i][j - 1][cnt - 1][v]) % MOD;
}
f[i][j][cnt][v] = (f[i][j][cnt][v] + f[i - 1][j][cnt][v]) % MOD;
f[i][j][cnt][v] = (f[i][j][cnt][v] + f[i][j - 1][cnt][v]) % MOD;
}
}
}
}
int ans = 0;
for (int i = 1; i <= 13; ++i)
ans = (ans + f[n][m][k][i]) % MOD;
cout << ans;
return 0;
}