zoukankan      html  css  js  c++  java
  • 2018年NOIP普及组复赛题解

    题目涉及算法:

    • 标题统计:字符串入门题;
    • 龙虎斗:数学题;
    • 摆渡车:动态规划;
    • 对称二叉树:搜索。

    标题统计

    题目链接:https://www.luogu.org/problem/P5015
    这道题目是一道基础题,考察你字符(串)的输入。
    实现代码如下:

    #include <cstdio>
    
    char c;
    int cnt;
    
    int main() {
    	while (c = getchar()) {
    		if (c == EOF || c == '
    ') break;
    		if (c != ' ') cnt ++;
    	}
    	printf("%d
    ", cnt);
    	return 0;
    }
    

    龙虎斗

    题目链接:https://www.luogu.org/problem/P5016
    这道题目是一道简单的数学推理题。
    但是它有一些条件是可以化简的,比如“某一刻天降神兵,共有 (s_1) 位工兵突然出现在了 (p_1) 号兵营”这个条件,你是可以直接处理成一开始这 (s_1) 位工兵就出现在 (p_1) 位置的。
    取出多余条件之后,实现的时候从左到右枚举一下势力和之差即可。
    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 100010;
    
    int n, m, p1, p2;
    long long a[maxn], s1, s2, sum;
    
    int main() {
    	cin >> n;
    	for (int i = 1; i <= n; i ++) cin >> a[i];
    	cin >> m >> p1 >> s1 >> s2;
    	a[p1] += s1;
    	p2 = 1;
    	for (int i = 1; i <= n; i ++)
    		sum += ( (long long) (i - m) ) * a[i];
    	for (int i = 1; i <= n; i ++)
    		if ( abs(sum + (i-m) * s2) < abs(sum + (p2-m) * s2) ) p2 = i;
    	cout << p2 << endl;
    	return 0;
    }
    

    摆渡车

    题目链接:
    本题涉及算法:动态规划,有一丢丢贪心的思想。
    我们令 (f[i]) 表示在时刻 (i) 发车时所有最晚在时刻 (i) 到站的人的最少等待时间,则:
    (f[i]) 只跟范围在 ((i-2*m, i-m])(f[j]) 有关,因为对于任意 (i) 来说:
    (f[i] le f[i-m]) (因为 (i-m) 时刻发车,我 (i) 又回来了)。
    那么我令 (tmp_{j,i}) 表示时刻 (j) 开始到时刻 (i) 到站的人的总等待时长,则:
    (f[i] = max(f[j]+tmp_{j,i})) (其中 (i-2 imes m lt j le i-m) )。
    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 4000400;
    
    int n, m, t, maxt;
    long long f[maxn], cnt[maxn];
    
    int main() {
    	cin >> n >> m;
    	for (int i = 0; i < n; i ++) {
    		cin >> t;
    		cnt[t] ++;
    		if (t > maxt) maxt = t;
    	}
    	for (int i = 0; i <= maxt + m; i ++) {
    		long long tmp = 0;
    		for (int j = 0; j < m && i-j >=0; j ++) {
    			tmp += cnt[i-j] * ( (long long) j );
    		}
    		f[i] = tmp;
    		if (i >= m) f[i] += f[i-m];
    		for (int j = m+1; j <= 2*m && i - j >= 0; j ++) {
    			tmp += cnt[i-j+1] * ( (long long) (j-1) );
    			if (f[i-j] + tmp <= f[i]) f[i] = f[i-j] + tmp;
    		}
    	}
    	long long ans = f[maxt];
    	for (int i = 1; i <= m; i ++) {
    		ans = min(ans, f[maxt+i]);
    	}
    	cout << ans << endl;
    	return 0;
    }
    

    对称二叉树

    题目链接:https://www.luogu.org/problem/P5018
    这道题目用搜索竟然过了。
    表示这样的话最坏情况下时间复杂度应该有 (O(n^2)) 囧、
    另说标准解法应该是树hash,有时间了解一下。
    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 4000400;
    
    int n, m, t, maxt;
    long long f[maxn], cnt[maxn];
    
    int main() {
    	cin >> n >> m;
    	for (int i = 0; i < n; i ++) {
    		cin >> t;
    		cnt[t] ++;
    		if (t > maxt) maxt = t;
    	}
    	for (int i = 0; i <= maxt + m; i ++) {
    		long long tmp = 0;
    		for (int j = 0; j < m && i-j >=0; j ++) {
    			tmp += cnt[i-j] * ( (long long) j );
    		}
    		f[i] = tmp;
    		if (i >= m) f[i] += f[i-m];
    		for (int j = m+1; j <= 2*m && i - j >= 0; j ++) {
    			tmp += cnt[i-j+1] * ( (long long) (j-1) );
    			if (f[i-j] + tmp <= f[i]) f[i] = f[i-j] + tmp;
    		}
    	}
    	long long ans = f[maxt];
    	for (int i = 1; i <= m; i ++) {
    		ans = min(ans, f[maxt+i]);
    	}
    	cout << ans << endl;
    	return 0;
    }
    
  • 相关阅读:
    漂亮的代码5:数组与字符一样的操作
    漂亮的代码4:缓存器的妙用
    漂亮的代码3:flatten 一个数组
    漂亮的代码2:遍历文件夹目录,使用promise
    漂亮的代码1:计算器
    nodejs 代码设计模式1:同步函数变异步
    [翻译]现代java开发指南 第二部分
    Httpclient远程调用WebService示例
    Java代码使用正则验证和常用工具方法
    简单将集合的内容转为字符串
  • 原文地址:https://www.cnblogs.com/codedecision/p/11821184.html
Copyright © 2011-2022 走看看