嗯重复一次,题目中带星号的是当时我没做出来的题。
真是很抱歉,因为这次做的非常不好,所以也就一直拖更,没有写这一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的话那就是铁定不能交换了。
做出这副新的矩阵之后我们要做的就是贪心法!从第一位开始遍历,尽可能的让小的靠在前面,这个就比较简单了,也就略过不提。
代码部分:
Problem C#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; }
题目概述:
主人公有一个书架,每次他想看书的时候都需要先将上面的所有书搬起来,然后把想要的这本书拿起来,然后放回搬起来的所有书,然后再把那本书读完之后放到顶上。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; }