• POJ 基础数据结构


    数据结构

    poj1035,poj3080,poj1936

    排序

    poj2388,poj2299

    简单并查集的应用

    poj1611

    哈希表和二分查找等高效查找法

    poj3349,poj3274,POJ2151(DP),

    poj1840,poj2002,poj2503

    哈夫曼树

    poj3253

    ,优先队列

    poj2442, poj1442

    trie

    poj2513, poj2418

     poj 1035

    分三种情况考虑。替换的话出入的字符串和dictionary只有一个不相同的。插入、删除的话比较与dictionary中相同的个数。

     poj 3080

    暴力过了,原来还有这么好用的strstr()函数。无语,我在那模拟了一晚上。。。

      用法:#include <string.h>
      功能:从字符串haystack中寻找needle第一次出现的位置(不比较结束符NULL)。
      说明:返回指向第一次出现needle位置的指针,如果没找到则返回NULL。
    View Code
    #include <iostream>
    #include <cstdio>
    #include <cstring>

    using namespace std;

    const int N = 15;

    char dic[N][66], s_max[66], tmp[66];

    int n;

    int cmp() {
    int ans, cnt, i, j, k;
    ans = 0; //len = strlen(dic[0]);

    for(i = 0; i < 60; ++i) {
    for(j = i; j < 60; ++j) {
    cnt = 0;
    for(k = i; k <= j; ++k) tmp[cnt++] = dic[0][k];
    tmp[cnt] = 0;

    for(k = 1; k < n; ++k)
    if(strstr(dic[k], tmp) == 0) break;
    if(k < n) continue;
    if(cnt > ans) {
    ans = cnt;
    strcpy(s_max, tmp);
    } else if(cnt == ans && strcmp(s_max, tmp) > 0) {
    strcpy(s_max, tmp);
    }
    }
    }
    return ans;
    }

    int main() {
    //freopen("data.in", "r", stdin);

    int t, i;
    scanf("%d", &t);
    while(t--) {
    scanf("%d", &n);

    getchar();
    for(i = 0; i < n; ++i) {
    cin.getline(dic[i], 66);
    //puts(dic[i]);
    }
    if(cmp() < 3) puts("no significant commonalities");
    else puts(s_max);
    }
    return 0;
    }


    poj 1936 水题
    poj 2388 复习了一下堆排序
    poj 2299

    题意是给一个无序的序列,两两交换两个元素的位置(这两个元素必须相邻)求需要交换多少次使这个序列成为有序不递减序列

    其实是让求逆序数是多少。这里用二路归并排序实现O(nlogn)的复杂度求逆序数。在实现一个二路归并排序过程中,前一半的序列x[i]跟后一半的序列y[j]分别有序。当出现x[i] > y[j]时,说明y[j]前边有mid - i + 1个数比y[j]大,累计逆序数。在网上看到一个很简洁的实现归并排序的代码,记下当模板

    View Code
     1 long long merge_sort(int l, int r) {
    2 int mid, p, q, i, j, len;
    3 long long ans = 0;
    4
    5 if(l >= r) return 0;
    6 mid = (l + r) >> 1;
    7 len = r - l + 1;
    8
    9 ans += merge_sort(l, mid);
    10 ans += merge_sort(mid + 1, r);
    11
    12 p = l; q = mid + 1;
    13 j = l;
    14
    15
    16 for(i = 0; i < len; ++i) {
    17 if((q > r) || (num[p] < num[q] && p <= mid)) {
    18 t[j++] = num[p++];
    19 } else {
    20 ans += mid - p + 1;
    21 t[j++] = num[q++];
    22 }
    23 }
    24 for(i = l; i <= r; ++i) num[i] = t[i];
    25
    26 return ans;
    27 }


    poj 1611

    建关系的时候写成O(n^2)了,跟si一样的700+ms过了,改过来后16+ms。貌似这题的数据不大,路径压缩起不到作用。=、=//

    poj 3349

    对每次输入的六个数求和取模,得到一个键值key,对键值相同的两个序列进行判断(这里用挂链存储),看是否匹配。判断匹配时可以把一个序列x增加一倍,扩展成长度为12的,比如

    x: 1, 2, 3, 4, 5, 6

    -> x: 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6

    然后跟

    另一个正序匹配一遍,倒序匹配一遍,如果可以匹配,返回true,否则返回false。

     poj 3274

    从大牛那学来的。。。

    sum[i][j]  表示第1到i个牛,j特征的总数。

    sum[i][0] - sum[j][0] == sum[i][1] - sum[j][1] == sum[i][2] - sum[j][2] = ...

    变形得

    sum[i][1] - sum[i][0] == sum[j][1] - sum[j][0];

    sum[i][2] - sum[i][0] == sum[j][2] - sum[j][0];

    。。。

    令c[i][L] = sum[i][L] - sum[i][0];

    比较c[i][...] == c[j][...]使 i - j 最大;

    可以用hashcode把c[i][...]折帖成一个值p,记录hash[p] = i;

    主过程:

    View Code
     1 int main() {
    2 //freopen("data.in", "r", stdin);
    3
    4 int n, k, i, j;
    5 int x, p, ans;
    6 while(~scanf("%d%d", &n, &k)) {
    7 memset(sum, 0, sizeof(sum));
    8 memset(hash, -1, sizeof(hash));
    9 memset(c, 0, sizeof(c));
    10 memset(a, 0, sizeof(a));
    11
    12 hash[hashcode(c[0], k)] = 0;
    13 ans = 0;
    14 for(i = 1; i <= n; ++i) {
    15 scanf("%d", &x);
    16 for(j = 0; j < k; ++j) {
    17 a[i][j] = x % 2;
    18 x >>= 1;
    19 sum[i][j] = sum[i-1][j] + a[i][j];
    20 c[i][j] = sum[i][j] - sum[i][0];
    21 }
    22 p = hashcode(c[i], k);
    23 while(hash[p] != -1) {
    24 for(j = 0; j < k; ++j) {
    25 if(c[i][j] != c[hash[p]][j]) break;
    26 }
    27 if(j == k) {
    28 ans = max(ans, i - hash[p]); break;
    29 }
    30 p++;
    31 }
    32 if(hash[p] == -1) hash[p] = i;
    33 }
    34 printf("%d\n", ans);
    35 }
    36 return 0;
    37 }


    POJ 2151

    貌似是道dp题。。。概率论没学好,在样例上纠结很长时间。

    设事件A = {所有队AC至少一题的概率},事件B = {所有的队都AC sum([1, N)题的概率)};

    用dp[i][j] 表示前i个题AC j道题的概率.

    dp[i][j] = dp[i-1][j] * (1 - p[i]) + dp[i-1][j-1] * p[i];

    memset(dp, 0, sizoef(dp));

    dp[0][0] = 1;

    dp[i][0] = dp[i-1][0] * (1 - p[i]);

     渣代码

    View Code
     1 #include <iostream>
    2 #include <cstdio>
    3 #include <cstring>
    4 #include <cstdlib>
    5
    6 using namespace std;
    7
    8 const int N = 100;
    9
    10 double dp[N][N];
    11 double p[N];
    12
    13 int main() {
    14 //freopen("data.in", "r", stdin);
    15
    16 int M, T, N;
    17 int i, j;
    18 double tol, d, cnt;
    19 while(~scanf("%d%d%d", &M, &T, &N)) {
    20 if(!M && !T && !N) break;
    21 tol = 1; d = 1;
    22 while(T--) {
    23 memset(dp, 0, sizeof(dp));
    24 dp[0][0] = 1;
    25
    26 for(j = 1; j <= M; ++j) {
    27 scanf("%lf", &p[j]);
    28 dp[j][0] = dp[j-1][0] * (1 - p[j]);
    29 }
    30
    31 tol *= (1 - dp[M][0]);
    32 if(N == 1) {d = 0; continue;}
    33
    34 for(i = 1; i <= M; ++i) {
    35 for(j = 1; j <= i && j < N; ++j) {
    36 dp[i][j] = dp[i-1][j]*(1 - p[i]) + dp[i-1][j-1]*p[i];
    37 }
    38
    39 }
    40 cnt = 0;
    41 for(j = 1; j < N; ++j) {
    42 cnt += dp[M][j];
    43 }
    44 d *= cnt;
    45 }
    46 printf("%.3f\n", tol - d);
    47 }
    48 return 0;
    49 }


    POJ 1840

    a*i3 + b*j3 + c*k3 + d*l3 + e*l3 = 0;

    a*i3 + b*j3 = - (d*l3 + e*l3+ c*k3 )   

    M + a*i3 + b*j3  =  M - (d*l3 + e*l3+ c*k3)   (M = 504*2)

    hash开到M*2,注意用char型

      

    POJ 2002

    不知道为什么,按上下左右找出四对点来不对,按abs(pt.x + pt.y)存hash,然后按下左排序枚举出来的就对了,无语!!

    POJ 2503

    map蹭过去了,写ELFhash不是wa就是TLE...

    POJ 3253

    离散数学上的最优树问题,用堆写的Huffman算法,结果用long long,int会超的。

    View Code
     1 #include <iostream>
    2 #include <cstdio>
    3 #include <cstring>
    4 #include <cmath>
    5
    6 using namespace std;
    7
    8 const int N = 20010;
    9
    10 int a[N];
    11
    12 void heap_adjust(int x, int n) {
    13 int i, j, tmp;
    14 i = x; j = i << 1;
    15 tmp = a[x];
    16 while(j <= n) {
    17 if(j < n && a[j+1] < a[j]) ++j;
    18 if(tmp > a[j]) {
    19 a[i] = a[j];
    20 i = j; j = i << 1;
    21 }
    22 else break;
    23 }
    24 a[i] = tmp;
    25 }
    26
    27 int main() {
    28 //freopen("data.in", "r", stdin);
    29
    30 int n, i;
    31 long long tmp, ans;
    32 while(~scanf("%d", &n)) {
    33 for(i = 1; i <= n; ++i)
    34 scanf("%d", a + i);
    35 for(i = n/2; i >= 1; --i) heap_adjust(i, n);
    36 ans = 0;
    37 while(1) {
    38 tmp = a[1]; a[1] = a[n--];
    39 heap_adjust(1, n);
    40
    41 tmp += a[1]; a[1] = tmp;
    42 heap_adjust(1, n);
    43
    44 ans += tmp;
    45 if(n == 1) break;
    46 }
    47 printf("%lld\n", ans);
    48 }
    49 return 0;
    50 }


    POJ 2513

    好久没写Trie树,这题是并查集+Trie树+判断是否存在两个以上的终点(度为奇数的点)

    开始没考虑到多个终点的问题,贡献wa若干。。。

    View Code
      1 #include <iostream>
    2 #include <cstring>
    3 #include <cstdio>
    4 #include <algorithm>
    5
    6 using namespace std;
    7
    8 const int N = 510000;
    9
    10 struct node {
    11 int flag;
    12 node *next[26];
    13 node() {
    14 flag = 0;
    15 for(int i = 0; i < 26; ++i)
    16 next[i] = NULL;
    17 }
    18 };
    19
    20 typedef struct node *Node;
    21
    22 int f[N], rank[N], deg[N], num;
    23
    24 int insert(Node &root, char *s) {
    25 int n = strlen(s);
    26 int i, t;
    27 Node p = root;
    28 for(i = 0; i < n; ++i) {
    29 t = s[i] - 'a';
    30 if(p->next[t] == NULL) {
    31 p->next[t] = new node;
    32 }
    33 p = p->next[t];
    34 }
    35 if(p->flag == 0)
    36 p->flag = num++;
    37 return p->flag;
    38 }
    39
    40 void del(Node &p) {
    41 int i;
    42 if(p) {
    43 for(i = 0; i < 26; ++i) {
    44 if(p->next[i])
    45 del(p->next[i]);
    46 }
    47 }
    48 delete p;
    49 p = NULL;
    50 }
    51
    52 void init() {
    53 int i;
    54 for(i = 0; i < N; ++i) f[i] = i, deg[i] = rank[i] = 0;
    55 num = 1;
    56 }
    57
    58 int find(int x) {
    59 int k = x, j;
    60 while(x != f[x]) x = f[x];
    61 while(k != x) {
    62 j = f[k];
    63 f[k] = x;
    64 k = j;
    65 }
    66 return x;
    67 }
    68
    69
    70 int main() {
    71 //freopen("data.in", "r", stdin);
    72
    73 char s1[20], s2[20];
    74 Node root;
    75 int i, x, y, cnt;
    76 init();
    77 root = new node;
    78 while(~scanf("%s %s", s1, s2)) {
    79 x = insert(root, s1);
    80 y = insert(root, s2);
    81 //printf("%d %d\n", x, y);
    82 deg[x]++; deg[y]++;
    83 x = find(x); y = find(y);
    84 if(x == y) continue;
    85
    86 if(rank[x] > rank[y]) f[y] = x;
    87 else {
    88 f[x] = y;
    89 if(rank[x] == rank[y]) ++rank[y];
    90 }
    91 }
    92 for(cnt = 0, i = 1; i < num; ++i) {
    93 if(deg[i]%2) cnt++;
    94 }
    95 x = find(1);
    96 for(i = 2; i < num; ++i) {
    97 if(find(i) != x) {
    98 puts("Impossible");
    99 return 0;
    100 }
    101 }
    102
    103 if(cnt <= 3) puts("Possible");
    104 else puts("Impossible");
    105 del(root);
    106 return 0;
    107 }



  • 相关阅读:
    数组迭代方法
    promise
    Gulp执行预处理
    第一个gulp 项目
    vue 单元素过渡
    webpack 入门
    webpack初始化
    v-for 指令
    ajax 工作原理
    面试小问题
  • 原文地址:https://www.cnblogs.com/vongang/p/2388814.html
Copyright © 2020-2023  润新知