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 }
View Code

因为每次 转移到了下一列 所以最后答案就是 dp[n+1][0][0][0]

posted @ 2020-10-27 13:05  canwinfor  阅读(146)  评论(0)    收藏  举报