codeforces GoodBye 2014 *A *B C(未完)

来源:互联网 发布:洛阳软件开发公司 编辑:程序博客网 时间:2024/05/22 07:56

嗯重复一次,题目中带星号的是当时我没做出来的题。

真是很抱歉,因为这次做的非常不好,所以也就一直拖更,没有写这一round的题解。


Problem A


题目概述:

嗯第一题嘛都是送分的题,题目说的是有一系列结点,12345对应abcde,然后你在第1个结点可以向右走a步,第二个结点走b步,依此类推。然后题目给定总共的结点数,以及想要到达的结点的位置,判断是否能够达到那个结点。

算法思想:

嗯嗯说实话确实是只要 res+=a[res] 就可以出来的解,但是我之所以没能做出来这道题(其实是做出来了,但是错在了test阶段),是因为边界的一个小问题,其实估计没有人会犯这个错误,实乃太丢人了。

代码部分:

#include <iostream>#include <string>#include <string.h>#include <map>#include <cmath>using namespace std;int n;int a[30005];int main() {int t;cin >> n >> t;for (int i = 1; i <= n; i++) {cin >> a[i];}int res = 1;while (res < t) {res += a[res];if (res == t) {cout << "YES" << endl;return 0;}}cout << "NO" << endl;return 0;}



Problem B

题目概述:

啧啧啧这道题目是说给定一个permutation,然后再给定一个关系矩阵表示i,j位置上的字母能否交换。要求输出字典序最小的排列方式。

算法思想:

当时没有做出来(或者说做错了)的原因主要是不愿意承认这是一幅图。。实际上那个关系图并不完全,因为比如说 i , j 可以交换,j , k 可以交换,但是 i , k位置上的数字可能是0。这就导致我们需要再处理一遍这个矩阵。

方法就是类似于弗洛伊德的遍历,如果i,j和j,k都是1的话,那就把i,k也设为1。这样的好处就是我们得到了一个完全的关系,也就是说如果此时检测到 i, j那个点为0的话那就是铁定不能交换了。

做出这副新的矩阵之后我们要做的就是贪心法!从第一位开始遍历,尽可能的让小的靠在前面,这个就比较简单了,也就略过不提。

代码部分:

#include <iostream>#include <string>#include <string.h>#include <map>#include <cmath>#include <algorithm>using namespace std;int n;int a[310][310];int b[310];int main() {cin >> n;for (int i = 1; i <= n; i++) {cin >> b[i];}for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {char s;cin >> s;a[i][j] = s - '0';}}//Floydfor (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {if (!a[j][i]) continue;for (int k = 1; k <= n; k++) {if (a[i][k] == 1) a[j][k] = 1;}}} for (int i = 1; i <= n; i++) {for (int j = i; j <= n; j++) {if (a[i][j] && b[i] > b[j]) swap(b[i], b[j]);}}for (int i = 1; i <= n; i++) {cout << b[i] << " ";}cout << endl;return 0;}


Problem C

题目概述:

主人公有一个书架,每次他想看书的时候都需要先将上面的所有书搬起来,然后把想要的这本书拿起来,然后放回搬起来的所有书,然后再把那本书读完之后放到顶上。ok现在问题来了,给定一个读书顺序,选一个最恰当的初始书籍排列顺序,然后计算在这个读书顺序时候需要提起来的最少的书籍重量是多少。

算法思想:

刚开始难倒我的部分其实是怎么进行这个书籍的排列,想了一段时间以后发现,其实最优排列顺序应该是“按第一次出现的顺序排列,比如阅读顺序是1232135634”这样,那么排列顺序应当是123564。证明略因为其实很好说明啦。

然后有了这个思想之后后面就还不算难了。我做的方法就是用list结构来模拟这个过程,按阅读顺序遍历,如果这本书还没有在list出现过,就push_back,否则的话就从头到尾遍历到那本书,把之前书的重量都加起来,得到总重量。这个方法感觉还是很好理解的。

代码部分:

#include <iostream>#include <list>#include <map>using namespace std;int n, m;int w[501];bool vis[501];int main() {    list<int> mylist;    cin >> n >> m;    for (int i = 1; i <= n; i++) {        cin >> w[i];    }    int res = 0;    for (int j = 1; j <= m; j++) {        int tmp;        cin >> tmp;        if (!vis[tmp]) {            mylist.push_back(tmp);            vis[tmp] = 1;        }        for (list<int>::iterator it = mylist.begin(); it != mylist.end(); ++it) {            if (*it == tmp) {                mylist.erase(it);                break;            }            res += w[(*it)];        }           mylist.push_front(tmp);    }    cout << res << endl;    return 0;}




0 0