标签:动态规划
思路
本题比较容易看出来是01背包的变形
注意到a的数据范围很大,dp数组是肯定存不下的,但是k的范围很小,而本题中要求魔力消耗总和是k的倍数,这就意味着如果a[i]%k==t,那么a[i]和t的贡献是一样,那么我们可以在输入a的时候直接对它取模,然后定义dp[i][j]为前i个符卡的魔力消耗总和膜k为j的最大值
代码实现
注意转移的时候,j-a[i]可能会小于0,这时不能直接膜k,而是要先加上一个k再取模
代码如下:
#include<stdio.h>
#include<iostream>
using namespace std;
int n,k;
int a[1005],b[1005];
long long dp[1005][1005];
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i]>>b[i];
a[i]%=k;
}
for(int i=0;i<=n;i++){
for(int j=0;j<k;j++){
dp[i][j]=-1e16;
}
}
dp[0][0]=0;
for(int i=1;i<=n;i++){
for(int j=0;j<k;j++){
dp[i][j]=max(dp[i-1][j],dp[i-1][(j-a[i]+k)%k]+b[i]);
}
}
if(dp[n][0]<=0) cout<<-1;
else cout<<dp[n][0];
return 0;
}