SMU Summer 2024 Contest Round 6
2024.7.22 9:00————11:00
过题数2/7
补题数4/7
- Many Formulas
- Tak and Cards
- Wall
- Coloring Edges on Tree
- Fault-tolerant Network
- Nearest Excluded Points
- Vacation Query
A - Many Formulas
题解:
给出一个包含只包含数字1到9的字符串s,长度最大为10,在这个字符串中任意位置加上‘+’得到的结果求和。
由于数字较小,2的九次方,直接二进制遍历即可,板子最好能熟悉一下。每次都得调试一段时间。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
string ss;
int s[12];
bool st[12];
int sum = 0;
int t;
void js() {
int res = s[0];
for (int p = 0; p < t-1;p++) {
if(!st[p]) {
res = res*10+s[p+1];
}
else {
sum += res;
res = s[p+1];
}
}
sum += res;
}//哦好像是这一段调试了一段时间,珍惜时间
signed main() {
cin >> ss;
t = ss.length();
for (int i = 0; i < t; i++) {
s[i] = ss[i] - '0';
}
for (int i = 0; i < (1 << t-1); i++) {
memset(st,0,sizeof st);
for (int j = 0; j < t-1; j++) {
if(i >> j & 1) {
st[j] = true;
}
}
js();
}
cout << sum;
return 0;
}
B - Tak and Cards
题解:
现在有n张卡片,给出一个数字a,可以取任意张卡片,使得平均值为a的方案有多少种。
一个比较典型的dp题,具体见注释。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 55;
int n,a;
int x[N];
int dp[55][2600];
//取i个物品总值为j的方案数
signed main() {
cin >> n >> a;
for (int i = 1; i <= n; i++) {
cin >> x[i];
}
memset(dp,0,sizeof dp);
dp[0][0] = 1;
//什么都不取也是一种情况
int sum = 0;
for (int i = 1; i <= n; i++) {
sum+=x[i];
//到当前位置的最大总值
for (int j = i; j >= 1; j--) {
//取j个
for (int k = sum; k >= x[i]; k--) {
//至少要取一个
dp[j][k]+= dp[j-1][k-x[i]];
//加上取了这个物品达到k的方案数
}
}
}
int ans = 0;
for (int i = 1; i <= n; i++) {
ans += dp[i][i*a];
//平均数
}
cout << ans;
return 0;
}
C - Wall
题解:
floyed算法,注意k在外面,之前写过不再赘述。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int h,w;
int c[10][10];
int a[210][210];
signed main() {
cin >> h >> w;
for (int i = 0; i <= 9; i++) {
for (int j = 0; j <= 9; j++) {
cin >> c[i][j];
}
}
for (int k = 0; k <= 9; k++) {
for (int i = 0; i <= 9; i++) {
for (int j = 0; j <= 9; j++) {
c[i][j] = min(c[i][j],c[i][k] + c[k][j]);
}
}
}
int ans = 0;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
cin >> a[i][j];
ans += c[a[i][j]][1];
}
}
cout << ans;
return 0;
}
D - Coloring Edges on Tree
题解:
一颗树有n个节点,有n-1条线连接任意俩个节点,现在给每条线涂色,要求每个节点的各个线段的颜色不同,问需要几个颜色,每条线涂什么颜色。
dfs实现,从连接线最多的节点向深度遍历,对它的所有线除了与父节点连的线以外涂色。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5+10;
int n;
int a[N],b[N];
int c[N];
vector<pair<int,int>>s[N];
void dfs(int x, int pre) {
int col = 1;
int t = -1;
for (auto m: s[x]) {
if(m.first == pre)t = m.second;
}//记录一下父节点那条线的颜色
for (auto q : s[x]) {
if(t!= -1) {
if(col == c[t])col++;
}
if(q.first == pre)continue;
//找到父节点不用给它上色
c[q.second] = col++;
dfs(q.first,x);
//继续往下找
}
}
signed main() {
cin >> n;
for (int i = 1; i < n; i++) {
cin >> a[i] >> b[i];
s[b[i]].push_back({a[i],i});
s[a[i]].push_back({b[i],i});
}
int ma = 0;
int wz;
for (int i = 1; i <= n; i++) {
if(s[i].size() > ma){
ma = s[i].size();
wz = i;
}
}cout << ma << endl;
//最小值其实就是最大节点的度
dfs(wz,0);
for (int i = 1; i < n; i++) {
cout << c[i] << endl;
}
return 0;
}