第36次CCF CSP计算机软件能力认证记录

本次应该是我最后一次参加CSP了,明年就毕业了。遗憾的是这次也仅仅只是拿了300分。需要走的路还很远很远。

csp300

今天去官网看见能把代码下载下来了,就记录一下。

然而这并不是完整的题解,只是我自身心路历程的记录。如果想看完整的题解的话我推荐这篇博客

第一题

简单模拟签到题。

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
#include<bits/stdc++.h>
using namespace std;
const int mxlen = 200;
int n,k;
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};

int types(char c){
if(c=='f') return 0;
if(c=='b') return 1;
if(c=='l') return 2;
if(c=='r') return 3;
}

void walk(int startx,int starty,string s){
for(int i=0;i<s.size();i++){
int tempx = startx+dx[types(s[i])];
int tempy = starty+dy[types(s[i])];
if(tempx<=0||tempx>n||tempy<=0||tempy>n) continue;
startx = tempx;
starty = tempy;
}
cout<<startx<<" "<<starty<<endl;
}
void work(){
string temp="";
int x,y;
for(int i=1;i<=k;i++){
cin>>x>>y>>temp;
walk(x,y,temp);
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T=1;
while(T--){
cin>>n>>k;
work();
}
return 0;
}

第二题

没有想出来正解,暴力算出来每个位置b变成0时需要的最少w。看别人的做法应该是用求和公式写不等式然后用前缀和做。出题人的仁慈,暴力有80分。

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
#include<bits/stdc++.h>
using namespace std;
const int mxlen = 1e5+10;
int n;
int a[mxlen],b[mxlen];
int needE[mxlen];
int work(int x){
int originE = 0;
int temp = 0;
for(int i=0;i<=n;i++){
if(i!=x) temp+=b[i];
temp-=a[i];
if(temp<0) {
originE+=-temp;
temp = 0;
}
}
return originE;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T=1;
while(T--){
cin>>n;
for(int i=0;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
cin>>b[i];
}
for(int i=1;i<=n;i++){
cout<<work(i)<<" ";
}
}
return 0;
}

第三题

模拟Cache,(学过计组的有福了)。但是最后应该是因为直接用二维数组暴力维护最近使用的内存所以TLE了一个点,只拿了90分。赛后想起来如果用deque声明数组做把排序操作时间复杂度降下来应该就能过了。

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include<bits/stdc++.h>
using namespace std;
const int mxlen = 10000;
int n,N;
struct node{
int id;
bool changed;
};

node v[mxlen][mxlen];

void init(){
for(int i=0;i<N;i++){
for(int j=0;j<n;j++){
v[i][j].id=-1;
}
}
}
void wirte(int id){
cout<<1<<" "<<id<<endl;
}
void read(int id){
cout<<0<<" "<<id<<endl;
}

bool findInCache(int id){
int i=(id/n)%N;
for(int j=0;j<n;j++){
if(v[i][j].id==-1)break;
if(v[i][j].id==id) return true;
}
return false;
}

void loadCache(int id){

int i=(id/n)%N;
node qw;
qw.id = id;qw.changed=0;
bool ok = 0;
for(int j=0;j<n;j++){
if(v[i][j].id==-1){
v[i][j].id=qw.id;
v[i][j].changed = qw.changed;
ok=1;
break;
}
}
if(ok) {read(id);;return;}
if(v[i][n-1].changed) wirte(v[i][n-1].id);
v[i][n-1].id = qw.id;
v[i][n-1].changed = qw.changed;
read(id);
}
void wirteCache(int id){
int i=(id/n)%N;
int pos = 0;
for(int j=0;j<n;j++){
if(v[i][j].id==id){
pos = j;
v[i][j].changed = 1;
break;
}
}
node temp;
temp.id = v[i][pos].id;
temp.changed = v[i][pos].changed;
for(int j=pos;j>0;j--){
v[i][j].id = v[i][j-1].id;
v[i][j].changed = v[i][j-1].changed;
}
v[i][0].id = temp.id;
v[i][0].changed = temp.changed;
}
void readInCache(int id){
int i=(id/n)%N;
int pos = 0;
for(int j=0;j<n;j++){
if(v[i][j].id==id){
pos = j;
break;
}
}
node temp;
temp.id = v[i][pos].id;
temp.changed = v[i][pos].changed;
for(int j=pos;j>0;j--){
v[i][j].id = v[i][j-1].id;
v[i][j].changed = v[i][j-1].changed;
}
v[i][0].id = temp.id;
v[i][0].changed = temp.changed;

}
void work(){
init();
int T;
cin>>T;
while(T--){
int type,a;
cin>>type>>a;
if(type==0){
if(findInCache(a)){
readInCache(a);
continue;
}else {
loadCache(a);
readInCache(a);
}
}else {
if(findInCache(a)){
wirteCache(a);
}else {
loadCache(a);
wirteCache(a);
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T=1;
while(T--){
cin>>n>>N;
work();
}
return 0;
}

第四题

这道题更是没有思路。正解应该是DP。赛场上只想到了把所有能到的点用边长为1的边连接,然后dijkstra求最短路,只拿了30分。

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
71
72
73
74
75
76
77
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mxlen = 2e6+10;
int n;
int a[mxlen],k[mxlen];

struct Edge{
ll v,w,next;
}G[mxlen];
ll head[mxlen],cnt;
void add(ll u,ll v,ll w){
cnt++;
G[cnt].w=w;
G[cnt].v=v;
G[cnt].next = head[u];
head[u] = cnt;
}
struct node {
ll d,u;
bool operator<(const node& t)const {
return d>t.d;
}
};

// int pre[mxlen],last[mxlen],other[mxlen],len[mxlen],l;

// void add(int x,int y,int z){
// l++;
// pre[l] = last[x];
// last[x] = l;
// other[l] = y;
// len[l] = z;
// }
ll dis[mxlen];

void work(){
memset(dis,0x3f,sizeof(dis));
dis[1] = 0;
priority_queue<node> q;
q.push((node){0,1});
while(!q.empty()){
node temp = q.top();
q.pop();
ll u =temp.u;
ll d = temp.d;
if(d!=dis[u]) continue;
for(int i=head[u];i;i=G[i].next){
ll v=G[i].v,w=G[i].w;
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
q.push((node){dis[v],v});
}
}
}
if(dis[n]==dis[0]) printf("-1");
else printf("%d",dis[n]);
}
int main(){
int T=1;
while(T--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
scanf("%d",&k[i]);
}
for(int i=1;i<=n;i++){
for(int j=i+1;j<=min(n,i+k[i]);j++){
add(i,j-a[j],1);
}
}
work();
}
return 0;
}

总结

最后时间不够了,也没有时间去分析最后一题了,看了一眼根本没看懂呜呜呜。