现在的位置: 首页 > 综合 > 正文

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

2017年10月16日 ⁄ 综合 ⁄ 共 2244字 ⁄ 字号 评论关闭

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

真是很抱歉,因为这次做的非常不好,所以也就一直拖更,没有写这一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';
		}
	}

	//Floyd
	for (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;
}

抱歉!评论已关闭.