PAT(甲级)2020年秋季考试(反思与代码)

    准备时间不算少也不算多,寒假就把题库刷了一遍,花的时间也不少,但是考前准备的不多,就是熟练一下解题的思路和模板。对于考试而言仍然有点碰运气的成分,赌他不会出动归,不会出一些数学题,不然就是歇菜,虽然我陈刀仔赌赢了,但是依然没有满分,最后一题图论两个点错误扣了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;
}

 

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值