思路:
首先说这道题很明显能看出来是一道dp啊,但是本人没看清题,没看到只有四个数,不会做
遂使用暴力大法
### 暴力大法好!!!!!!
说回来这道题的的dfs还死活非常好写的哈
首先我们需要一个vis来标记每张牌是不是已经用过了,然后我们就按找“找哪个”的思路去做就好了
## 强烈推荐大家去看b上灵山的视频,关于dfs与dp讲的太好了!二者丝滑转换(我还做不到)
def dfs(i, s):
global ans,a
if i == n-1:
ans += score[n-1]
a = max(a,ans)
ans -= score[n-1]
return
ans += score[i]
for ind, j in enumerate(card):
if vis[ind] != -1:
vis[ind] = -1
path.append(j)
dfs(j + i, ans)
path.pop()
vis[ind] = 1
ans -= score[i]
当然,dfs的时间复杂度是不能通过这道题的,现在我们思考dp
首先当然是找状态(ps.我每次想不出来我就现在脑海里构建一个dfs的框架,然后以dfs每次的状态作为状态基本就错不了,没办法,实在是想不出来)
所以我们的状态就是当前处在的格子所积攒的分数
其次就是找状态转移方程:
这时候我们要注意一件事,就是只有四个分数的牌,而我们如果不考虑这个条件,而是把所有的card的话是找不到状态转移方程的(也可能是我实在是太弱了)
然后我们构建的状态就是:
dp[i][j][k][g]
这代表着已经使用了i张走一步的,j张走两步的……以此类推
状态转移方程也可以很轻松的找到:
dp[i][j][k][g] = max(dp[i-1][j][k][g], dp[i][j-1][k][g], dp[i][j][k-1][g], dp[i][j][k][g-1],dp[i][j][k][g])
这道题就做完啦!总的来说这道题还是非常简单的
代码
n, m = map(int,input().split())
score = list(map(int, input().split()))
card = list(map(int, input().split()))
# 一共走m步,选哪个的问题,n个格子
# dp[i] = max(dp[i-k],dp[i])
vis = [1] * (n + 1)
dp = [0] * n
def dfs(i, s):
global ans,a
if i == n-1:
ans += score[n-1]
a = max(a,ans)
ans -= score[n-1]
return
ans += score[i]
for ind, j in enumerate(card):
if vis[ind] != -1:
vis[ind] = -1
path.append(j)
dfs(j + i, ans)
path.pop()
vis[ind] = 1
ans -= score[i]
vis = [1] * (n + 1)
# 四维dp
# dp[i][j][k][g]:只有四个数
a = b= c= d =0
for i in card:
if i == 1:
a += 1
if i == 2: b += 1
if i == 3: c += 1
if i == 4: d += 1
dp = [[[[0] * (d+1) for _ in range(c+1)]for _ in range(b+1)]for _ in range(a+1)]
# dp[i] = max(dp[i-k] + score[i], dp[i])
for i in range(a+1):
for j in range(b+1):
for k in range(c+1):
for g in range(d+1):
cur = i + 2 * j + 3 * k + 4 * g
dp[i][j][k][g] = max(dp[i-1][j][k][g], dp[i][j-1][k][g], dp[i][j][k-1][g], dp[i][j][k][g-1],dp[i][j][k][g])
dp[i][j][k][g] += score[cur]
print(dp[a][b][c][d])
3万+



被折叠的 条评论
为什么被折叠?



