[2018百度之星] 初赛(A)A-C题解

链接:http://bestcoder.hdu.edu.cn/contests/contest_show.php?cid=825

这场出的三题,有两道和标算不太一样啊。。。其中一道题还是因为数据弱暴力过的,感觉这样下去不太行啊。。。

A:直接按照长短排序,从大到小连续取3根,看看能不能构成三角形。取最大的三根就行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <bits/stdc++.h>
using namespace std;

const int maxn = 1100;
int n, a[maxn];

signed main() {
// freopen("in", "r", stdin);
while(~scanf("%d", &n)) {
for(int i = 0; i < n; i++) {
scanf("%d",&a[i]);
}
sort(a, a+n);
int ret = 0;
int ok = 0;
for(int i = n - 1; i > 1; i--) {
if(a[i]<a[i-1]+a[i-2]) {
ok = 1;
ret = a[i]+a[i-1]+a[i-2];
break;
}
}
if(!ok) printf("-1\n");
else printf("%d\n", ret);
}
return 0;
}

B:这里直接用deque或者list暴力就行,其实应该手写一个list,然后接头接尾直接翻转两个指针。(其实我想到了,但是写不来。码力太差了啊。。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <bits/stdc++.h>
using namespace std;

const int maxn = 150100;
int n, q;
vector<deque<int>> l;

inline bool scan_d(int &num) {
char in;bool IsN=false;
in=getchar();
if(in==EOF) return false;
while(in!='-'&&(in<'0'||in>'9')) in=getchar();
if(in=='-'){ IsN=true;num=0;}
else num=in-'0';
while(in=getchar(),in>='0'&&in<='9'){
num*=10,num+=in-'0';
}
if(IsN) num=-num;
return true;
}

signed main() {
freopen("in", "r", stdin);
int u, v, w, val;
while(scan_d(n)) {
l.resize(n+1);
scan_d(q);
for(int i = 1; i <= n; i++) l[i].clear();
int cmd;
while(q--) {
scan_d(cmd);
if(cmd == 1) {
scan_d(u); scan_d(w); scan_d(val);
if(w == 0) l[u].emplace_front(val);
else l[u].emplace_back(val);
}
if(cmd == 2) {
scan_d(u); scan_d(w);
if(l[u].size() == 0) {
printf("-1\n");
continue;
}
if(w == 0) {
printf("%d\n", l[u].front());
l[u].pop_front();
}
else {
printf("%d\n", l[u].back());
l[u].pop_back();
}
}
if(cmd == 3) {
scan_d(u); scan_d(v); scan_d(w);
if(w == 0) {
while(!l[v].empty()) {
l[u].emplace_back(l[v].front());
l[v].pop_front();
}
}
else {
while(!l[v].empty()) {
l[u].emplace_back(l[v].back());
l[v].pop_back();
}
}
}
}
}
return 0;
}

C:(一道比较简单的签到题),这题我在第17分钟的时候就提交了DP做法,就是先把1串拆出来,两头的花费为1,中间的花费为2,然后做背包容量为k+1的01背包,一开始想的是最左花费为0,后来觉得不太对,有可能拆分后原先最左不在最左了,于是分了两种情况讨论了一下。折腾了2h才步入正轨。。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <bits/stdc++.h>
using namespace std;

const int maxn = 10100;
int n, k;
char s[maxn];
vector<pair<int, int>> seg;
int f[maxn], L, R;

int gao2() {
seg.clear();
int i = 0;
while(i < n) {
if(s[i] == '1') {
int j = i, tot = 0;
while(j < n && s[j] == '1') {
tot++, j++;
}
if(i == 0) seg.push_back(make_pair(tot, 1));
else if(j == n) seg.push_back(make_pair(tot, 1));
else seg.push_back(make_pair(tot, 2));
i = j;
}
else i++;
}
if(k == 1) {
if(s[0] == '1') {
return seg[0].first;
}
else return 0;
}
memset(f, 0, sizeof(f));
for(int i = 0; i < seg.size(); i++) {
for(int j = k; j >= seg[i].second; j--) {
f[j] = max(f[j], f[j-seg[i].second]+seg[i].first);
}
}
return f[k];
}
signed main() {
// freopen("in", "r", stdin);
while(~scanf("%d%d",&n,&k)) {
scanf("%s", s);
k++;
printf("%d\n", gao2());
}
return 0;
}

赛后感觉应该把B C D按照正解做一下。。