Codeforces Round #677 (Div. 3)
F. Zero Remainder Sum
直接dfs枚举所有情况, 然后在加个记忆化
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int dp[80][80][70][80];
int mp[100][100], k, n, m;
bool judge(int x, int y) {
if (x < 1 || y < 1 || x > n || y > m) {
return false;
}
return true;
}
int dfs(int x, int y, int cnt, int sum) {
if (!judge(x, y)) {
if (sum == 0) {
return 0;
}
return -1e8;
}
if (dp[x][y][cnt][sum] != -1) return dp[x][y][cnt][sum];
int ans = -1e8;
ans = max(ans, dfs(x, y + 1, cnt, sum));
ans = max(ans, dfs(x + 1, 1, 0, sum));
if (cnt < m / 2) {
ans = max(ans, dfs(x, y + 1, cnt + 1, (sum + mp[x][y]) % k ) + mp[x][y]);
}
if (cnt < m / 2) {
ans = max(ans, dfs(x + 1, 1, 0, (sum + mp[x][y]) % k ) + mp[x][y]);
}
return dp[x][y][cnt][sum] = ans;
}
int main() {
cin >> n >> m >> k;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> mp[i][j];
}
}
memset(dp, -1, sizeof(dp));
cout << dfs(1, 1, 0, 0) << endl;
}
G. Reducing Delivery Cost
先用迪杰斯特拉跑多源最短路, 求出(dist[i][j]) i 到j的最短距离, 然后枚举删的边(u, v) 假设当前要算的是 s到t的最短路, 删掉u,v时 那么最短路有可能变成,(dist[s][u] + dist[v][t])或者 (dist[s][v] + dist[u][t])或者是(dist[s][t])取最小就行了
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3 + 7;
int dist[N][N], n, m, k, vis[N] ;
vector<pair<int, int> > g[N];
struct node {
int d, v;
bool operator <(const node x) const{
return d > x.d;
}
};
priority_queue<node>q;
void dj (int s) {
for (int i = 1; i <= n; i++) {
dist[s][i] = 1e8;
vis[i] = 0;
}
dist[s][s] = 0;
q.push({0, s});
while (q.size()) {
node cd = q.top();
q.pop();
if (vis[cd.v]) continue;
vis[cd.v] = 1;
for (auto it: g[cd.v]) {
int to = it.first;
int cost = it.second;
if (dist[s][to] > dist[s][cd.v] + cost) {
dist[s][to] = dist[s][cd.v] + cost;
q.push({dist[s][to], to});
}
}
}
}
vector<pair<int, int> >cnt;
struct edge{
int u, v, w;
};
vector<edge>e;
int main() {
cin >> n >> m >> k;
for (int i = 1; i <= m; i++) {
int u, v, w;
cin >> u >> v >> w;
g[u].push_back({v, w});
g[v].push_back({u, w});
e.push_back({u, v, w});
}
for (int i = 1; i <= k; i++) {
int u, v;
cin >> u >> v;
cnt.push_back({u, v});
}
for (int i = 1; i <= n; i++) {
dj(i);
}
long long ans = 0;
for (int i = 0; i < cnt.size(); i++) {
ans += 1ll* dist[cnt[i].first][cnt[i].second];
}
long long minn = INT_MAX;
for (int i = 0; i < e.size(); i++) {
ll cat = ans;
int u = e[i].u, v = e[i].v, w = e[i].w;
for (int j = 0; j < cnt.size(); j++) {
ll res = dist[cnt[j].first][u] + dist[cnt[j].second][v];
ll cn = 0;
if (res < dist[cnt[j].first][cnt[j].second]) {
cn = dist[cnt[j].first][cnt[j].second] - res;
}
res = dist[cnt[j].first][v] + dist[cnt[j].second][u];
if (res < dist[cnt[j].first][cnt[j].second]) {
cn = max(cn, dist[cnt[j].first][cnt[j].second] - res);
}
cat = cat - cn;
}
minn = min(minn, cat);
}
cout << minn << endl;
}