10 篇文章 9 订阅

# 问题一：开心的金明

### 题目描述

v[j1​]×w[j1​]+v[j2​]×w[j2​]+⋯+v[jk​]×w[jk​]。

### 输入输出样例

1000 5
800 2
400 5
300 5
400 3
200 2


3900

## 【代码】

不滚动

N, m = map(int, input().split())
dp = [[0] * (N + 1) for _ in range(m + 1)]

v = [0] * (m + 1); p = [0] * (m + 1)
for i in range(1, m + 1):
v[i], p[i] = map(int, input().split())
for i in range(1, m + 1):
for j in range(0, N + 1):
if j < v[i]:
dp[i][j] = dp[i - 1][j]
else:
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - v[i]] + v[i] * p[i])
print(dp[m][N])

交替滚动

N, m = map(int, input().split())
dp = [[0] * (N + 1) for _ in range(2)]

v = [0] * (m + 1); p = [0] * (m + 1)
for i in range(1, m + 1):
v[i], p[i] = map(int, input().split())

now, old = 0, 1
for i in range(1, m + 1):
now, old = old, now
for j in range(0, N + 1):
if j < v[i]:
dp[now][j] = dp[old][j]
else:
dp[now][j] = max(dp[old][j], dp[old][j - v[i]] + v[i] * p[i])
print(dp[now][N])

自我滚动

N, m = map(int, input().split())
dp = [0] * (N + 1)

v = [0] * (m + 1); p = [0] * (m + 1)
for i in range(1, m + 1):
v[i], p[i] = map(int, input().split())

for i in range(1, m + 1):
for j in range(N, v[i] - 1, -1):
dp[j] = max(dp[j], dp[j - v[i]] + v[i] * p[i])
print(dp[N])

# 题目二：积木画

### 样例输入

3


### 样例输出

5


## 【思路】

dp[i][j]：前i-1个位置铺满的情况下， 第i个位置的第j个状态的情况数

​​​​​​

## 【代码】

Python3（非滚动数组实现）(TLE)

n = int(input())
MOD = int(1e9) + 7
g = [[1, 1, 1, 1], [0, 0, 1, 1], [0, 1, 0, 1], [1, 0, 0, 0]]
dp = [[0] * 4 for _ in range(n + 10)]

dp[1][0] = 1
for i in range(1, n + 1):
for j in range(4):        # 第i列的状态j
for k in range(4):    # 第j列的状态k
if g[j][k] == 1:  # 第i列的状态j可以转移第j列的状态k
dp[i + 1][k] = (dp[i + 1][k] + dp[i][j]) % MOD
print(dp[n + 1][0]) 

C++ (滚动数组实现) (AC)

#include <iostream>
#include <string.h>
using namespace std;
const int N = 1e7 + 10, MOD = 1e9 + 7;
int dp[2][4];
int g[4][4] = {{1, 1, 1, 1}, {0, 0, 1, 1}, {0, 1, 0, 1}, {1, 0, 0, 0}};
int main()
{
int n; cin >> n;
int old = 0, now = 1;
dp[now][0] = 1;
for (int i = 1; i <= n; i++) {
swap(now, old);
memset(dp[now], 0 ,sizeof(dp[now]));
for (int j = 0; j < 4; j++) {
for (int k = 0; k < 4; k++ ) {
dp[now][k] = (dp[now][k] + dp[old][j] * g[j][k]) % MOD;
}
}
}
cout << dp[now][0];
return 0;
}

• 3
点赞
• 2
收藏
觉得还不错? 一键收藏
• 打赏
• 0
评论
12-19
09-30
10-19
02-12
01-23
06-02
06-24
06-24
10-10
12-21
09-01
06-10

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

¥2 ¥4 ¥6 ¥10 ¥20

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、C币套餐、付费专栏及课程。