chenchen题解:NOIP2015-S

下面是NOIP2015提高组初赛错题整理

具有 n 个节点,e 条边的图采用邻接表存储结构,进行深度优先遍历和广度优先遍历运算的时间复杂度为( O(e+n)

解释:因为在遍历时我们有st数组来防止重复访问,故没每一个节点只访问一次,所以是e+n

双向链表中有两个指针域,llinkrlink,分别指回前驱及后继,设 p 指向链表中的一个结点,q 指向一待插入结点,现要求在 p 前插入 q,则正确的插入为( )

p->llink->rlink=q;
q->rlink=p;
q->llink=p->llink;
p->llink=q;

解释:
p左边元素的右边位置是q
q的右边元素是p
q左边元素是原来p的左边元素
p的左边元素是q

3.对图 G 中各个结点分别指定一种颜色,使相邻结点颜色不同,则称为图 G 的一个正常着色。正常着色图 G 所必需的最少颜色数,称为 G 的色数。那么下图的色数是

chenchen题解:NOIP2015-S_第1张图片
解释:
3 看图
chenchen题解:NOIP2015-S_第2张图片

在 1 和 2015 之间(包括 1 和 2015 在内)不能被 4、5、6 三个数任意一个数整除的数有_____个。

解释:
1075个
容斥原理:2015-能被4整除的-能被5整除的-能被6整除的+能被4和5整除的+能被5和6整除的+能被4和6整除的-能被4和5和6整除的
注意几和几表示的是最小公倍数

(双子序列最大和)给定一个长度为n(3≤n≤1000) 的整数序列,要求从中选出两个连续子序列,使得这两个连续子序列的序列和之和最大,最终只需输出这个最大和。一个连续子序列的序列和为该连续子序列中所有数之和。要求:每个连续子序列长度至少为 1,且两个连续子序列之间至少间隔 1 个数。

#include 
using namespace std;
const int MAXN = 1000;
int n, i, ans, sum;
int x[MAXN];
int lmax[MAXN];
// lmax[i] 为仅含 x[i] 及 x[i] 左侧整数的连续子序列的序列和中,最大的序列和
int rmax[MAXN];
// rmax[i] 为仅含 x[i] 及 x[i] 右侧整数的连续子序列的序列和中,最大的序列和

int main() {
    cin >> n;
    for (i = 0; i < n; i++) cin >> x[i];
    lmax[0] = x[0] ;
    for (i = 1; i < n; i++)
        if (lmax[i - 1] <= 0)
            lmax[i] = x[i];
        else
            lmax[i] = lmax[i - 1] + x[i];
    for (i = 1; i < n; i++)
        if (lmax[i] < lmax[i - 1])
            lmax[i] = lmax[i - 1];;
    for (i = n - 2; i >= 0; i --)
        if (rmax[i + 1] <= 0);
        else;
    for (i = n - 2; i >= 0; i --)
        if (rmax[i] < rmax[i + 1]);
    ans = x[ 0] + x [2];
    for (i = 1; i < n - 1; i++) {
        sum =;
        if (sum > ans)
            ans = sum;
    }
    cout << ans << endl;
    return 0;

解释:
①初始化,由于n为最后一个,所以最大值就是x[n-1]
②同上,如果后面再没有的话最大值就是它本身
③如果不是最后一个,最大值就是后面的最大值再加上它本身
④打擂台求最大长度
⑤最后更新sum,等于左边的最大加上右边的最大

(最短路径问题)无向连通图 G 有 n 个结点,依次编号为 0,1,2·····,n-2,n-1。用邻接矩阵的形式给出每条边的边长,要求输出以结点 00为起点出发,到各结点的最短路径长度。
使用 Dijkstra 算法解决该问题:
利用 dist 数组记录当前各结点与起点的已找到的最短路径长度;
每次从未扩展的结点中选取 dist 值最小的结点 v 进行扩展,更新与 v 相邻的结点的 dist 值;
不断进行上述操作直至所有结点均被扩展,此时 dist 数据中记录的值即为各结点与起点的最短路径长度。

#include 
using namespace std;
const int MAXV = 100;
int n, i , j, v;
int w[MAXV][MAXV]; // 邻接矩阵,记录边长
// 其中 w[i][j] 为连接结点 i 和结点 j 的无向边长度,若无边则为 -1
int dist[MAXV];
int used[MAXV]; // 记录结点是否已扩展(0:未扩展;1:已扩展)
int main() {
    cin >> n;
    for (i = 0; i < n; i+ +)
        for (j = 0; j < n; j++)
            cin >> w[i][j];
    dist[0] = 0;
    for (i = 1; i < n; i+ +)
        dist[i] = -1;
    for (i = 0; i < n; i+ +)
        used[i] = 0;
    while (true) {;
        for (i = 0; i < n; i++)
            if (used[i] != 1 && dist[i] != -1 && (v == -1 ||));
        if(v == -1)
            break;;
        for (i = 0; i < n; i++)
            if (w[v][i] != -1 && (dist[i] == -1 ||))
                dist[i] = dist[v] + w[v][i];
    }
    for (i = 0; i < n; i++)
        cout << dist[i] << endl;
    return 0;
}

解释:
①现将v初始化成-1表示还没有更新
②打擂台找到与当前点距离最短的点并扩展
③更新,扩展
④记录已经被更新过了
⑤借助该点进行松弛操作

在这里插入图片描述

你可能感兴趣的:(算法)