Codeforces Round #677 (Div. 3)

F. Zero Remainder Sum || dp

 

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 73;

int a[maxn][maxn], dp[maxn][maxn][maxn][maxn], d[maxn][maxn];

int main()
{
    int n, m, k;
    scanf("%d %d %d", &n, &m, &k);
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
            scanf("%d", &a[i][j]);
    memset(dp, -1, sizeof(dp));
    memset(d, -1, sizeof(d));
    for(int i = 1; i <= n; ++i) dp[i][0][0][0] = 0;
    for(int i = 1; i <= n; ++i)//第i行
    {
        for(int j = 0; j < m; ++j)//考虑到第j+1个数是否取
        {
            for(int k1 = 0; k1 <= m/2; ++k1)//取k1个数
            {
                for(int k2 = 0; k2 < k; ++k2)//sum%k等于k2
                {
                    if(dp[i][j][k1][k2] == -1) continue;
                    dp[i][j+1][k1][k2] = max(dp[i][j][k1][k2], dp[i][j+1][k1][k2]);
                    dp[i][j+1][k1+1][(k2+a[i][j+1])%k] = max(dp[i][j][k1][k2] + a[i][j+1], dp[i][j+1][k1+1][(k2+a[i][j+1])%k]);
                }
            }
        }
    }
    d[0][0] = 0;
    dp[0][m][0][0] = 0;
    for(int i = 0; i < n; ++i)//前i行
    {
        for(int j = 0; j < k; j++)//sum%k等于j
        {
            for(int k1 = 0; k1 <= m / 2; k1++)
            {
                for(int k2 = 0; k2 < k; k2++)
                {
                    if(d[i][j] == -1) continue;
                    if(dp[i+1][m][k1][k2] == -1) continue;
                    d[i+1][(j+k2)%k] = max(d[i][j] + dp[i+1][m][k1][k2], d[i+1][(j+k2)%k]);
                }
            }
        }
    }
    printf("%d\n", d[n][0]);
    return 0;
}

 

G. Reducing Delivery Cost || 图论最短路
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const int maxn = 1005;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;

struct edge
{
    int to, cost;
    edge(int k1, int k2): to{k1}, cost{k2} {}
};
int d[maxn], road[maxn][2], dist[maxn][maxn], route[maxn][2];
vector<edge> G[maxn];
priority_queue< P, vector<P>, greater<P> > que;     //第一维记录cost,第二维记录to

void Dijkstra(int s)
{
    memset(d, INF, sizeof(d));
    d[s] = 0;
    que.push(P(0, s));

    while(!que.empty())
    {
        P p = que.top(); que.pop();
        int v = p.second;
        if(d[v] < p.first) continue;             //去掉已经被访问过的节点和被更新过的边长
        for(unsigned int i = 0; i < G[v].size(); i++)   //更新边长
        {
            edge e = G[v][i];
            if(d[e.to] > d[v] + e.cost)
            {
                d[e.to] = d[v] + e.cost;
                que.push(P(d[e.to], e.to));
            }
        }
    }
}

int main()
{
    int n, m, k, sum = 0;
    scanf("%d %d %d", &n, &m, &k);
    for(int i = 1; i <= m; ++i)
    {
        int u, v, w;
        scanf("%d %d %d", &u, &v, &w);
        G[u].push_back(edge(v, w));
        G[v].push_back(edge(u, w));
        road[i][0] = u, road[i][1] = v;
    }
    for(int i = 1; i <= n; ++i)
    {
        Dijkstra(i);
        for(int j = 1; j <= n; ++j) dist[i][j] = d[j];
    }
    int ans = 0;
    for(int i = 1; i <= k; ++i)
    {
        scanf("%d %d", &route[i][0], &route[i][1]);
        ans += dist[route[i][0]][route[i][1]];
    }
    int r = 0;
    for(int i = 1; i <= m; ++i)
    {
        sum = 0;
        for(int j = 1; j <= k; ++j)
        {
            int tmp = min(dist[route[j][0]][road[i][0]] + dist[route[j][1]][road[i][1]], dist[route[j][0]][road[i][1]] + dist[route[j][1]][road[i][0]]);
            sum += max(dist[route[j][0]][route[j][1]] - tmp, 0);
        }
        r = max(r, sum);
    }
    printf("%d\n", ans - r);
    return 0;
}

 

posted @ 2020-10-22 03:28  .Ivorelectra  阅读(130)  评论(0编辑  收藏  举报