Codeforces Round #677 (Div. 3) F. Zero Remainder Sum ###K ###K //K
题目链接:https://codeforces.ml/contest/1433/problem/F
题意:给定一个矩阵,每一行最多取不超过m/2个数 问怎么取才能是 总和最大且%k==0
思路: 每个数取和不取 01背包问题 范围不大 用四维dp即可 也可以优化成三维
dp[i][j][x][y] 代表到第i行j列 取了x个数 取模为y的最大值是多少
按照取了恰好x个数来写
此时全部状态是非法,初始化dp[1][0][0][0]=0 每次更新dp[i+1]的时候 不一定能取这么多数,所以要枚举一遍
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define pb push_back 5 const int maxn =1e5+10; 6 const int mod=1e9+7; 7 8 int dp[75][75][75][75]; 9 int a[75][75]; 10 11 12 13 int main() 14 { 15 ios::sync_with_stdio(false); 16 cin.tie(0); 17 int n,m,k; 18 cin>>n>>m>>k; 19 for(int i=1;i<=n;i++) 20 for(int j=1;j<=m;j++) 21 cin>>a[i][j]; 22 23 24 memset(dp,-0x3f,sizeof(dp)); 25 dp[1][0][0][0]=0; 26 for(int i=1;i<=n;i++) 27 { 28 for(int j=1;j<=m;j++) 29 { 30 for(int x=0;x<=m/2;x++) 31 { 32 for(int y=0;y<k;y++) 33 { 34 int &t=dp[i][j][x][y]; 35 t=dp[i][j-1][x][y]; 36 int g=a[i][j]%k; 37 if(x) t=max(t,dp[i][j-1][x-1][(y-g+k)%k]+a[i][j]); 38 } 39 } 40 } 41 for(int y=0;y<k;y++) 42 { 43 int mx=-1e9; 44 for(int x=0;x<=m/2;x++) mx=max(mx,dp[i][m][x][y]); 45 dp[i+1][0][0][y]=mx; 46 } 47 } 48 cout<<dp[n+1][0][0][0]<<'\n'; 49 50 51 52 53 54 55 }
因为每次 转移到了下一列 所以最后答案就是 dp[n+1][0][0][0]

浙公网安备 33010602011771号