The 18th Zhejiang Provincial Collegiate Programming Contest题解
A. League of Legends
水题。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[6];
int b[6];
signed main()
{
for(int i = 1; i <= 5; i++) cin >> a[i];
for(int i = 1; i <= 5; i++) cin >> b[i];
int num1 = 0, num2 = 0;
for(int i = 1; i <= 5; i++){
num1 += a[i];
num2 += b[i];
}
if(num1 >= num2){
printf("Blue\n");
}
else printf("Red\n");
return 0;
}
L、String Freshman
首字母出现两次即为不合格。因为这样会造成忽略。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n;
char s[100010];
int main()
{
scanf("%d%s", &n, s + 1);
for(int i = 2; i <= n; i++) if(s[i] == s[1]) return puts("Wrong Answer"), 0;
puts("Correct");
return 0;
}
G、Wall Game
用map维护坐标编号,用并查集维护连通块,合并的时候维护连通块内的坐标数量和应删除边即可。
点击查看代码
#pragma GCC optimize (2)
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long
template <class T>
inline void read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){
if(c == '-') s = -1;
c = getchar();
}
while(isdigit(c)){
x = x * 10 + (c ^ '0');
c = getchar();
}
a = x * s;
return ;
}
map <pair<int, int>, int> G;
int fa[N];
int find_fa(int x){
return x == fa[x] ? x : fa[x] = find_fa(fa[x]);
}
int n;
int tot = 0;
int del[N]; // del: 每个联通块应当删去的边的个数
int num[N];
int fx[7] = {0, 1, 1, -1, -1, 0, 0};
int fy[7] = {0, 0, -1, 0, 1, 1, -1};
inline void merge(int u, int v, int delta){
int fau = find_fa(fa[u]), fav = find_fa(fa[v]);
if(fau != fav){
num[fav] += num[fau];
del[fav] += del[fau] + delta;
fa[fau] = fav;
}
return ;
}
void seek(int x, int y){
int dx, dy;
del[G[make_pair(x, y)]] = 0;
num[G[make_pair(x, y)]] = 1; // 1个点
set <int> s;
map <int, int> g;
for(int i = 1; i <= 6; i++){
dx = x + fx[i];
dy = y + fy[i];
if(!G.count(make_pair(dx, dy))) continue; // dx,dy 没有被占领
s.insert(find_fa(G[make_pair(dx, dy)]));
g[find_fa(G[make_pair(dx, dy)])]++;
}
for(auto it : s){
merge(find_fa(G[make_pair(x, y)]), it, g[it]);
}
return ;
}
int main(){
read(n);
for(int i = 1; i <= (int)1e6; i++)
fa[i] = i;
for(int i = 1; i <= n; i++){
int opt, x, y;
read(opt), read(x), read(y);
if(!G.count(make_pair(x, y))) G[make_pair(x, y)] = ++tot;
if(opt == 1){
// 向六个边去找
seek(x, y);
}
else {
int f = find_fa(G[make_pair(x, y)]);
// printf("x: %d y: %d id: %d num: %d del: %d\n", x, y, find_fa(G[make_pair(x, y)]), num[f], del[f]);
printf("%d\n", num[f] * 6 - del[f] * 2);
}
}
return 0;
}
J、Grammy and Jewelry | header |
最短路加完全背包
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long
template <class T>
inline void read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
a = x * s;
return ;
}
int n, m, T;
struct node{
int u, v, w, next;
/* data */
} t[N << 1];
int head[N];
int bian = 0;
inline void addedge(int u, int v, int w){
t[++bian] = (node){u, v, w, head[u]}, head[u] = bian;
return ;
}
int a[N];
ll dis[N];
bool vis[N];
struct point{
int id;
ll dis;
bool operator < (const point &a) const{
return dis > a.dis;
}
} ;
void dij(int s){
memset(vis, 0, sizeof(vis));
memset(dis, 0x3f3f3f3f3f3f3f, sizeof(dis));
priority_queue <point> q;
q.push((point){s, 0});
dis[s] = 0;
while(!q.empty()){
int u = q.top().id; q.pop();
if(!vis[u]){
vis[u] = 1;
for(int i = head[u]; i; i = t[i].next){
int v = t[i].v;
if(dis[v] > dis[u] + t[i].w){
dis[v] = dis[u] + t[i].w;
if(!vis[v]) q.push((point){v, dis[v]});
}
}
}
}
return ;
}
ll dp[N]; // i 时间内的最多价值
int main(){
// freopen("hh.txt", "r", stdin);
read(n), read(m); read(T);
for(int i = 2; i <= n; i++) read(a[i]);
for(int i = 1; i <= m; i++){
int x, y;
read(x), read(y);
addedge(x, y, 1);
addedge(y, x, 1);
}
dij(1);
for(int i = 2; i <= n; i++){
for(int j = dis[i] * 2; j <= T; j++){
if(j - (dis[i] << 1) >= 0){ // 完全背包,可以选择无数次(不断从前面的累加)
dp[j] = max(dp[j], dp[j - (dis[i] << 1)] + a[i]);
}
}
}
for(int i = 1; i <= T; i++)
printf("%lld ", dp[i]);
return 0;
}