准备时间不算少也不算多,寒假就把题库刷了一遍,花的时间也不少,但是考前准备的不多,就是熟练一下解题的思路和模板。对于考试而言仍然有点碰运气的成分,赌他不会出动归,不会出一些数学题,不然就是歇菜,虽然我陈刀仔赌赢了,但是依然没有满分,最后一题图论两个点错误扣了4分,发现错误点的时候还有40分钟,然而却越改错的越多,可能说明一个问题,我还有错误没有发现,但是由于我的代码写的比较宽泛,把一些数据点给漏过去了,但是当我认真改起来的时候发现错的更多了,按水平可能最后一题连26都拿不了,能拿真是天助我也。
考前对此前考过的题和自己的水平也是有所估量的,以我现在的水平很难稳稳拿满,除非题目特别简单,否则必须有惊艳的操作才能如愿,而这次可以说是无功无过加上运气成分。而提升到目标水准可能又是几百道题,甚至这个水准并不存在客观的度量,acmer们做pat可能就轻松多了。
第一题(AC)
思路:(1)合并相邻且相同的数据,存入结构体。
(2)寻找低谷,并以每个低谷为中心向两边扩展,取max值。
反思:没有第一时间审明白题,不过理解题后思路比较清晰,但是却也没有考虑什么极端数据,测完样例就提交了,好在过了。
#include<iostream>
#include<vector>
#include<math.h>
#include<algorithm>
using namespace std;
int panda[10005], last = 0;
struct node {
int w, num;
};
vector<node>list;
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &panda[i]);
if (panda[i] == last) {
list[list.size() - 1].num++;
}
else {
list.push_back({panda[i],1});
}
last = panda[i];
}
vector<int>distr(list.size());
vector<int>islight;
if (list[0].w < list[1].w)islight.push_back(0);
for (int i = 1; i < list.size() - 1; i++)
if (list[i].w < list[i + 1].w&&list[i].w < list[i - 1].w)islight.push_back(i);
if (list[list.size() - 1].w < list[list.size() - 2].w)islight.push_back(list.size() - 1);
for (int i = 0; i < islight.size(); i++) {
int it = islight[i],next;
if (i != islight.size() - 1)next = islight[i + 1];
else next = list.size()-1;
distr[it] = 200;
for (int j = it; j >= 1; j--) { //向前回溯
if (list[j - 1].w > list[j].w)distr[j - 1] = max(distr[j - 1], distr[j] + 100);
else break;
}
for (int j = it; j < next; j++) {
if (list[j + 1].w > list[j].w)distr[j + 1] = max(distr[j + 1], distr[j] + 100);
else break;
}
}
int sum = 0;
for (int i = 0; i < distr.size(); i++)
sum += distr[i] * list[i].num;
cout << sum;
return 0;
}
第二题(AC)
水题
#include<iostream>
#include<vector>
#include<math.h>
#include<algorithm>
using namespace std;
int piece[10005];
int main() {
int n, m, cnt = 0;
scanf("%d%d", &n,&m);
for (int i = 0; i < n; i++)scanf("%d", &piece[i]);
for (int i = 0; i < n; i++) {
int tpsum = 0;
for (int j = 0; j < n&&i + j < n; j++) {
tpsum += piece[i + j];
if (tpsum <= m)cnt++;
else break;
}
}
cout << cnt;
return 0;
}
第三题(AC)
思路:(1)前中建树(刷过题库的应该写烂了)
(2)层序遍历,把每一层第一个元素弄出来。
由于考试最后系统崩溃,没能复制出来代码。
第四题(26)
(9.20更新)
刚刚有个妹子大佬指出我没有判环,并给出一个满分答案,我裂开了,我能拿分可能是因为教育商店充钱了吧。以下为满分答案。
#include <bits/stdc++.h>
using namespace std;
const int NMAX = 1005;
const int MAX_DIS = 500;
struct Edge {
int v;
int score, daijinquan;
Edge() {};
Edge(int _v, int _score, int _daijinquan) {
v = _v;
score = _score;
daijinquan = _daijinquan;
}
};
vector<Edge> graph[NMAX];
int in[NMAX], in_buff[NMAX];
int n, m;
void not_consist() {
// 有环,直接判断
cout << "Impossible." << endl;
int k;
cin >> k;
while (k--) {
int node;
cin >> node;
if (in[node] == 0)
printf("You may take test %d directly.
", node);
else
printf("Error.
");
}
}
//vector<int> pre[NMAX];
int pre[NMAX];
void Dijkstra() {
bool visited[NMAX];
int dis_score[NMAX];
int dis_daijinquan[NMAX];
fill(visited, visited + NMAX, false);
fill(dis_score, dis_score + NMAX, MAX_DIS);
fill(dis_daijinquan, dis_daijinquan + NMAX, 0);
//dis_score[n]=0;
//int node;
for (Edge e:graph[n]) {
dis_score[e.v] = dis_daijinquan[e.v] = 0;
pre[e.v] = n;
}
while (true) {
int min_node = n;
int min_dis = MAX_DIS;
for (int i = 0; i < n; i++) {
if (visited[i])
continue;
if (dis_score[i] < min_dis) {
min_dis = dis_score[i];
min_node = i;
} else if (dis_score[i] == min_dis) {
if (dis_daijinquan[i] > dis_daijinquan[min_node])
min_node = i;
}
}
if (min_node == n)
break;
visited[min_node] = true;
for (Edge e:graph[min_node]) {
if (min_dis + e.score < dis_score[e.v]) {
pre[e.v] = min_node;
dis_score[e.v] = min_dis + e.score;
dis_daijinquan[e.v] = dis_daijinquan[min_node] + e.daijinquan;
} else if (min_dis + e.score == dis_score[e.v]) {
if (dis_daijinquan[min_node] + e.daijinquan > dis_daijinquan[e.v]) {
pre[e.v] = min_node;
dis_daijinquan[e.v] = dis_daijinquan[min_node] + e.daijinquan;
}
}
}
}
}
void consist() {
// 无环 Djs算法
cout << "Okay." << endl;
Dijkstra();
int k;
cin >> k;
for (int i = 0; i < k; i++) {
int dst;
cin >> dst;
if (pre[dst] == n) {
printf("You may take test %d directly.
", dst);
} else {
vector<int> path;
while (dst != n) {
path.push_back(dst);
dst = pre[dst];
}
int l = path.size();
printf("%d", path[l - 1]);
for (int j = l - 2; j >= 0; j--) {
printf("->%d", path[j]);
}
printf("
");
}
}
}
bool check() {
// 判断是否有环
bool visited[NMAX];
fill(visited, visited + NMAX, false);
for (int i = 0; i < n; i++) {
int node = 0;
for (; node < n; node++) {
if (!visited[node] && in[node] == 0) {
break;
}
}
if (node == n)
break;
visited[node] = true;
for (Edge t:graph[node]) {
in[t.v]--;
}
}
for (int i = 0; i < n; i++) {
if (in[i])
return false;
}
return true;
}
int main() {
cin >> n >> m;
for (int i = 0; i < m; i++) {
int u, v, s, d;
cin >> u >> v >> s >> d;
in[v]++;
in_buff[v]++;// 入读保存两份,一份用来判环,一份判断是否是启示节点(一开始入读就是0的节点)
graph[u].push_back(Edge(v, s, d));
}
for (int i = 0; i < n; i++) {
if (in[i] == 0) {
// 用节点n作为总起始节点,连接所有起始入度为零的节点,将图变成单源的
graph[n].push_back(Edge(i, 0, 0));
}
}
if (check())
consist();
else
not_consist();
return 0;
}
(以下是原文)
思路(1)每次输入一个点判断它是否可以直接输出。
(2)如果可以直接输出或者前提条件具备,就以他为其实更新他相邻的点。
(3)如果它输入进去发现不能直接输出且他的前驱们都没有更新过信息,那么就是error。
(4)数据更新两个指标,一个是所需分数要最少(距离),另一个是优惠券更多。
问题:不应该使用后来的考试的更优数据去更新前面的考试的数据。
#include<iostream>
#include<vector>
#include<math.h>
#include<algorithm>
#include<queue>
#include<stdlib.h>
using namespace std;
struct node {
int s, d;
};
node qmap[1005][1005];
vector<int>path,ans;
int mins=65536, maxd=0,f[1005];
vector<vector<int>>behind;
vector<vector<int>>quis;
int lastnode[1005],score[1005],darr[1005],seq[1005],pos[1005];
void dfs(int s) { //本来想写dfs的,写着写着发现是dij的一个子步骤,没改函数名
for (int i = 0; i < behind[s].size(); i++)
{
int next = behind[s][i];
f[next] = 1;
if (score[s] + qmap[s][next].s < score[next]) {
score[next] = score[s] + qmap[s][next].s;
darr[next] = darr[s] + qmap[s][next].d;
lastnode[next] = s;
}
else if (score[s] + qmap[s][next].s == score[next]&&darr[s]+qmap[s][next].d>darr[next]) {
darr[next] = darr[s] + qmap[s][next].d;
lastnode[next] = s;
}
}
}
void getpath(int s) {
path.push_back(s);
if (lastnode[s] == -1)
return;
else getpath(lastnode[s]);
}
int main() {
int n, m,k;
scanf("%d%d", &n, &m);
behind=vector<vector<int>>(n + 1);
quis = vector<vector<int>>(n + 1);
for (int i = 0; i < m; i++) {
int t1, t2, s, d;
scanf("%d%d%d%d", &t1, &t2, &s, &d);
qmap[t1][t2] = {s,d};
behind[t1].push_back(t2);
quis[t2].push_back(t1);
}
scanf("%d", &k);
for (int i = 0; i <= n; i++) {
f[i] = 0;
score[i] = 65536;
darr[i] = 0;
lastnode[i] = -1;
}
bool flag = true;
for (int i = 0; i < k; i++) {
scanf("%d", &seq[i]);
int tp = seq[i];
pos[tp] = i;
}
for (int i = 0; i < k; i++) {
int tp = seq[i];
if (f[tp] || quis[tp].size() == 0) {
if (quis[tp].size() == 0) {
f[tp] = 1;
score[tp] = 0;
darr[tp] = 0;
}
}
else {
flag = false;
f[i+10]=1;
}
for (int j = 0; j <= i; j++)
if (f[seq[j]])dfs(seq[j]);
}
if (flag)printf("Okay.\n");
else printf("Impossible.\n");
for (int i = 0; i < k; i++) {
int tp = seq[i];
if (!f[tp])printf("Error.\n");
else {
if (lastnode[tp] == -1)printf("You may take test %d directly.\n", tp);
else {
path.clear();
getpath(tp);
reverse(path.begin(), path.end());
for (int x = 0; x < path.size(); x++)
if (x == 0)printf("%d", path[x]);
else printf("->%d", path[x]);
printf("\n");
}
}
}
return 0;
}