2019/03/18 完成01-02node
2019/03/19 完成03ios
2019/03/20 完成04git
2019/03/21 完成05(unordered_set)算法
2019/03/22 完成05(手写哈希),06数组
2019/03/23 完成07性能
#include <iostream> #include <stack> #include <vector> using namespace std; using intpair = pair<int, int>; const int INF{0x3f3f3f3f}; int main(int argc, char *argv[]) { cin.sync_with_stdio(false); int N, M, S, D; cin >> N >> M >> S >> D; vector<int> vec(N); for (int i = 0; i != N; ++i) cin >> vec[i]; vector<vector<intpair>> road(N); for (int i = 0; i != M; ++i) { int mbeg, mend, mvel; cin >> mbeg >> mend >> mvel; road[mbeg].push_back({mend, mvel}); road[mend].push_back({mbeg, mvel}); } vector<int> dijkstra(N, INF), mov(N), cross(N), mins(N); vector<bool> known(N, false); dijkstra[S] = 0; mov[S] = vec[S]; cross[S] = -1; mins[S] = 1; while (1) { int minval{INF}, minindex{-1}; for (int i = 0; i != N; ++i) { if (known[i] == false && dijkstra[i] != INF && dijkstra[i] < minval) { minindex = i; minval = dijkstra[i]; } } if (minindex == -1) break; known[minindex] = true; for (const auto &i : road[minindex]) { if (dijkstra[minindex] + i.second < dijkstra[i.first]) { dijkstra[i.first] = dijkstra[minindex] + i.second; mov[i.first] = mov[minindex] + vec[i.first]; cross[i.first] = minindex; mins[i.first] = mins[minindex]; } else if (dijkstra[minindex] + i.second == dijkstra[i.first]) { if (mov[minindex] + vec[i.first] > mov[i.first]) { mov[i.first] = mov[minindex] + vec[i.first]; cross[i.first] = minindex; } mins[i.first] += mins[minindex]; } } } cout << mins[D] << ' ' << mov[D] << endl; stack<int> ST; int tD{D}; ST.push(D); while (cross[tD] != -1) { ST.push(cross[tD]); tD = cross[tD]; } bool fis = true; while (!ST.empty()) { if (fis) fis = false; else cout << ' '; cout << ST.top(); ST.pop(); } cout << endl; return EXIT_SUCCESS; }
Dijkstra算法 学习
#include <iostream> #include <vector> using namespace std; using intpair = pair<int, int>; int main(int argc, char *argv[]) { int beginnode, cnt; scanf("%d%d", &beginnode, &cnt); vector<intpair> LinkNode(100000); vector<int> book(100001); while (cnt--) { int beg, val, next; scanf("%d%d%d", &beg, &val, &next); LinkNode[beg] = {val, next}; } int disp{-1}, dispold{beginnode}, temp{-1}, temp2{-1}; while (beginnode != -1) { if (book[abs(LinkNode[beginnode].first)]) { if (disp == -1) disp = temp = beginnode; else { LinkNode[temp].second = beginnode; temp = beginnode; } } else { if (temp2 != -1) LinkNode[temp2].second = beginnode; temp2 = beginnode; book[abs(LinkNode[beginnode].first)] = true; } beginnode = LinkNode[beginnode].second; } LinkNode[temp2].second = LinkNode[temp].second = -1; beginnode = dispold; if (beginnode != -1) { printf("%05d %d", beginnode, LinkNode[beginnode].first); beginnode = LinkNode[beginnode].second; while (beginnode != -1) { printf(" %05d\n%05d %d", beginnode, beginnode, LinkNode[beginnode].first); beginnode = LinkNode[beginnode].second; } printf(" -1\n"); } beginnode = disp; if (beginnode != -1) { printf("%05d %d", beginnode, LinkNode[beginnode].first); beginnode = LinkNode[beginnode].second; while (beginnode != -1) { printf(" %05d\n%05d %d", beginnode, beginnode, LinkNode[beginnode].first); beginnode = LinkNode[beginnode].second; } printf(" -1\n"); } return EXIT_SUCCESS; }
考察数组模拟链表;上面的实现的稍有麻烦,彻底修正了链表地址,分开了两个链表;然而根据题目输出要求,这是没有必要的!能够直接开两个vector存储下两个链表的地址,以下。测试
#include <iostream> #include <vector> using namespace std; using intpair = pair<int, int>; intpair LinkNode[100000]; int book[100001]{0}; int main(int argc, char *argv[]) { int beginnode, cnt; scanf("%d%d", &beginnode, &cnt); while (cnt--) { int beg, val, next; scanf("%d%d%d", &beg, &val, &next); LinkNode[beg] = {val, next}; } vector<int> a, b; while (beginnode != -1) { if (book[abs(LinkNode[beginnode].first)]) b.push_back(beginnode); else { a.push_back(beginnode); book[abs(LinkNode[beginnode].first)] = true; } beginnode = LinkNode[beginnode].second; } if (!a.empty()) { printf("%05d %d", a[0], LinkNode[a[0]].first); for (decltype(a.size()) i = 1; i != a.size(); ++i) printf(" %05d\n%05d %d", a[i], a[i], LinkNode[a[i]].first); printf(" -1\n"); } if (!b.empty()) { printf("%05d %d", b[0], LinkNode[b[0]].first); for (decltype(b.size()) i = 1; i != b.size(); ++i) printf(" %05d\n%05d %d", b[i], b[i], LinkNode[b[i]].first); printf(" -1\n"); } return EXIT_SUCCESS; }
#include <algorithm> #include <iostream> #include <vector> using namespace std; using mypair = pair<double, double>; bool mypaircompare(const mypair &a, const mypair &b) { return a.second > b.second; } int main(int argc, char *argv[]) { int cnt, need; scanf("%d%d", &cnt, &need); vector<mypair> vec(cnt); for (int i = 0; i < cnt; ++i) scanf("%lf", &vec[i].first); for (int i = 0; i < cnt; ++i) { double temp; scanf("%lf", &temp); vec[i].second = temp / vec[i].first; } sort(vec.begin(), vec.end(), mypaircompare); double cost{0.0}; for (int i = 0; i < cnt; ++i) { if (need >= vec[i].first) { need -= vec[i].first; cost += vec[i].first * vec[i].second; if (!need) break; } else { cost += need * vec[i].second; break; } } printf("%.2lf\n", cost); return EXIT_SUCCESS; }
简单的贪心;老题目了,须要注意库存量和总售价都是浮点数,样例输入是整数具备迷惑性…哈哈 ui
#include <algorithm> #include <iostream> #include <vector> using namespace std; int array[1001]{0}; vector<int> T; bool mir; bool buildtree(int beg, int ed) { if (beg > ed) return true; int root{array[beg]}, mid; int temp{beg + 1}; if (mir) { while (temp <= ed && array[temp] >= root) ++temp; mid = temp - 1; while (temp <= ed && array[temp] < root) ++temp; } else { while (temp <= ed && array[temp] < root) ++temp; mid = temp - 1; while (temp <= ed && array[temp] >= root) ++temp; } if (temp != ed + 1) return false; bool re = buildtree(beg + 1, mid) && buildtree(mid + 1, ed); T.push_back(root); return re; } int main(int argc, char *argv[]) { int cnt; scanf("%d", &cnt); for (int i = 1; i <= cnt; ++i) scanf("%d", &array[i]); mir = false; bool isp{true}; if (!buildtree(1, cnt)) { mir = true; T.clear(); isp = buildtree(1, cnt); } if (isp) { printf("YES\n"); for (auto i = T.begin(); i != T.end(); ++i) { if (i != T.begin()) putchar(' '); printf("%d", *i); } putchar('\n'); } else printf("NO\n"); return EXIT_SUCCESS; }
根据二叉搜索树的前序遍历,输出后序遍历。由于只须要输出后序遍历,因此咱们并不须要真正的建树,按照左子树、右子树、根节点的次序把后序遍历存储下来就能够啦。spa
基础题上加了个花样,便可能是“镜像二叉搜索树”;先假定不是镜像的,遍历一次;若是遍历失败,就假定是镜像的,再尝试一次,两次都失败输出“NO”,成功就输出存储后序遍历的vector。
#include <algorithm> #include <iostream> #include <set> #include <unordered_set> #include <vector> using namespace std; int main(int argc, char *argv[]) { int cnt; scanf("%d", &cnt); vector<unordered_set<int>> SET(cnt); for (int i = 0; i != cnt; ++i) { int ind; scanf("%d", &ind); while (ind--) { int temp; scanf("%d", &temp); SET[i].insert(temp); } } scanf("%d", &cnt); while (cnt--) { int a, b; scanf("%d%d", &a, &b); --a, --b; int sum{0}; for (const auto &i : SET[a]) if (SET[b].find(i) != SET[b].end()) ++sum; printf("%.2lf%%\n", (sum * 1.0) / (SET[a].size() + SET[b].size() - sum) * 100.0); } return EXIT_SUCCESS; }
这是专门为STL库准备的题啊?…元素数目较多,且不须要顺序排列,选用哈希构造的 unordered_set ! 最后一个测试点耗时仅需92ms。
emmm,这道题的本意应该是考察哈希表,若是语言标准库里没有的话得本身写;端正学习态度后,头铁一波……
自写哈希表,采用平方探测法/装填因子保证在0.33 。
#include <algorithm> #include <cmath> #include <cstring> #include <iostream> #include <vector> using namespace std; struct SThash { int *hash; int hmax, cnt; }; bool isprime(int num) { if (num < 2) return false; for (int i = 2; i <= (int)sqrt(num); ++i) if (num % i == 0) return false; return true; } int NextPrime(int num) { while (!isprime(num)) ++num; return num; } SThash *buildhash(int cnt) { cnt = NextPrime(cnt * 3); SThash *T = (SThash *)malloc(sizeof(SThash)); T->hash = (int *)malloc(cnt * sizeof(int)); T->hmax = cnt; T->cnt = 0; memset(T->hash, -1, cnt * sizeof(int)); return T; } void insert(SThash *T, int value) { int temp{value % T->hmax}, base{0}; while (T->hash[temp] != -1) { if (T->hash[temp] == value) return; temp += ((++base) << 1) - 1; if (temp >= T->hmax) temp -= T->hmax; } T->hash[temp] = value; ++T->cnt; return; } bool find(SThash *T, int value) { int temp{value % T->hmax}, base{0}; while (T->hash[temp] != -1 && T->hash[temp] != value) { temp += ((++base) << 1) - 1; if (temp >= T->hmax) temp -= T->hmax; } if (T->hash[temp] == value) return true; return false; } int getdigit(void) { int temp{0}; char ch; while (1) { ch = getchar(); if (ch == ' ' || ch == '\n' || ch == EOF) return temp; temp = temp * 10 + ch - '0'; } return -1; } int main(int argc, char *argv[]) { int cnt{getdigit()}; SThash *HashTable[50]; for (int i = 0; i != cnt; ++i) { int ind{getdigit()}; HashTable[i] = buildhash(ind); while (ind--) { int temp{getdigit()}; insert(HashTable[i], temp); } } cnt = getdigit(); while (cnt--) { int a{getdigit()}, b{getdigit()}; --a, --b; int sum{0}; for (int i = 0; i != HashTable[a]->hmax; ++i) if (HashTable[a]->hash[i] != -1 && find(HashTable[b], HashTable[a]->hash[i])) ++sum; printf("%.2lf%%\n", (sum * 1.0) / (HashTable[a]->cnt + HashTable[b]->cnt - sum) * 100.0); } return EXIT_SUCCESS; }
性能和 unordered_set 差很少。
#include <iostream> #include <queue> #include <vector> using namespace std; struct node { int left, right; }; node tree[35]; vector<int> a, b; int buildtree(int left1, int right1, int left2, int right2) { if (left1 > right1) return -1; int root{a[right1]}, i; for (i = left2; i <= right2; ++i) if (root == b[i]) break; int lenl{i - left2 - 1}, lenr{right2 - i - 1}; --right1; tree[root].left = buildtree(left1, left1 + lenl, left2, i - 1); tree[root].right = buildtree(right1 - lenr, right1, i + 1, right2); return root; } void BFS(int root) { queue<int> Q; Q.push(root); printf("%d", root); while (!Q.empty()) { root = Q.front(); if (tree[root].left != -1) { Q.push(tree[root].left); printf(" %d", tree[root].left); } if (tree[root].right != -1) { Q.push(tree[root].right); printf(" %d", tree[root].right); } Q.pop(); } putchar('\n'); return; } int main(int argc, char *argv[]) { int cnt; scanf("%d", &cnt); for (int i = 0; i != cnt; ++i) { int temp; scanf("%d", &temp); a.push_back(temp); } for (int i = 0; i != cnt; ++i) { int temp; scanf("%d", &temp); b.push_back(temp); } BFS(buildtree(0, cnt - 1, 0, cnt - 1)); return EXIT_SUCCESS; }
建树;写的并不熟练,须要增强这方面的练习。
#include <algorithm> #include <iostream> #include <vector> using namespace std; using intpair = pair<int, int>; int unions[10000]; intpair spunions[10000]; struct ans { int index, number; double Ecnt, Esum; }; bool sortcompare(const ans &a, const ans &b) { if (a.Esum == b.Esum) return a.index < b.index; return a.Esum > b.Esum; } int DSUfind(const int &num) { if (unions[num] <= -1) return num; return unions[num] = DSUfind(unions[num]); } void DSUunion(const int &a, const int &b) { int spa{DSUfind(a)}, spb{DSUfind(b)}; if (spa != spb) { if (spa < spb) { unions[spa] += unions[spb]; spunions[spa].first += spunions[spb].first; spunions[spa].second += spunions[spb].second; unions[spb] = spa; } else { unions[spb] += unions[spa]; spunions[spb].first += spunions[spa].first; spunions[spb].second += spunions[spa].second; unions[spa] = spb; } } } int main(int argc, char *argv[]) { fill(begin(unions), end(unions), -1); int cnt; scanf("%d", &cnt); while (cnt--) { int a, b, c; scanf("%d%d%d", &a, &b, &c); if (b != -1) DSUunion(a, b); if (c != -1) DSUunion(a, c); int cntt; scanf("%d", &cntt); while (cntt--) { int child; scanf("%d", &child); DSUunion(a, child); } scanf("%d%d", &b, &c); int temp{DSUfind(a)}; spunions[temp].first += b; spunions[temp].second += c; } vector<ans> ANS; for (int i = 0; i < 10000; ++i) { if (unions[i] < -1 || (unions[i] == -1 && spunions[i].first)) { ans temp; temp.index = i; temp.number = -unions[i]; temp.Ecnt = spunions[i].first / (double)temp.number; temp.Esum = spunions[i].second / (double)temp.number; ANS.push_back(temp); } } sort(ANS.begin(), ANS.end(), sortcompare); printf("%llu\n", ANS.size()); for (const auto &i : ANS) printf("%04d %d %.3lf %.3lf\n", i.index, i.number, i.Ecnt, i.Esum); return EXIT_SUCCESS; }
考察并查集。合并操做的同时注意合并房产套数和总面积,以后再计算平均值,按要求排序后输出。