爆炸的符卡洋洋洒洒题解报告
标签:动态规划
来源:牛客网
解题思路:
显而易见的背包问题
但再观察a,b的数据范围,开不了那么大的dp数组
这就启发我们去优化,由于题目要求魔力总耗的是k的倍数
我们可以对每个数据魔力消耗对k取模
使用dp[][j]中直接保存 魔力总和取模后为j时的最大威力
那么动态转移方程:
dp[i][j] = max(dp[i-1][j],dp[i-1][((j-a)%k+k)%k]+b);
做到这我才发现和九小时九个人九扇门那道题是同个道理,比赛时没做出来实在可惜
代码实现:
#include <bits/stdc++.h>
using namespace std;
long long dp[1050][1050];
int main(){
int n,k;
cin>>n>>k;
int a,b;
memset(dp,-0x3f,sizeof(dp));
dp[0][0]=0;
for(int i=1;i<=n;i++){
cin>>a>>b;
for(int j=0;j<k;j++){
dp[i][j] = max(dp[i-1][j],dp[i-1][((j-a)%k+k)%k]+b);
}
}
long long ans = dp[n][0];
if(ans<=0) ans=-1;
cout<<ans<<endl;
return 0;
}