• PAT 1065 1066 1067 1068


    pat 1065 A+B and C                                         

    主要是注意一下加法溢出的情况,不要试图使用double,因为它的精度是15~16位,不能满足精度要求,代码如下:

     1 #include<cstdio>
     2 #include<climits>
     3 #include<cmath>
     4 //double精度为15~16位,不能满足精度要求
     5 int main()
     6 {
     7     int testNum;
     8     scanf("%d",&testNum);
     9     long long MAX = LONG_LONG_MAX; //pow(2,63) - 1,
    10     long long MIN = LONG_LONG_MIN; //-1*pow(2,63);
    11     for(int i = 1; i <= testNum; i++)
    12     {
    13         long long a,b,c;
    14         scanf("%lld %lld %lld", &a, &b, &c);
    15 
    16         if(a >= 0 && b >=0)
    17         {
    18             if(MAX - a >= b)
    19                 goto NORMAL;
    20             else
    21             {
    22                 printf("Case #%d: true
    ", i);
    23                 continue;
    24             }
    25         }
    26         else if(a < 0 && b < 0)
    27         {
    28             if(MIN - a <= b)
    29                 goto NORMAL;
    30             else
    31             {
    32                 printf("Case #%d: false
    ", i);
    33                 continue;
    34             }
    35         }
    36         else ;
    37 
    38 NORMAL:
    39         if(a + b > c)
    40             printf("Case #%d: true
    ", i);
    41         else
    42             printf("Case #%d: false
    ", i);
    43     }
    44     return 0;
    45 }
    View Code

    pat 1066 Root of AVL Tree                                          本文地址

    最基本的AVL树的操作,关于AVL树可以参考herehere,代码如下:

      1 #include<cstdio>
      2 #include<climits>
      3 #include<cmath>
      4 
      5 //operate of AVL tree
      6 
      7 inline int max2(int a, int b)
      8 {
      9     return a>b? a:b;
     10 }
     11 
     12 struct avlnode
     13 {
     14     struct avlnode *rson;
     15     struct avlnode *lson;
     16     int data;
     17     int height;
     18 };
     19 
     20 inline int height(struct avlnode *tree)
     21 {
     22     if(NULL == tree)
     23         return -1;
     24     else return tree->height;
     25 }
     26 
     27 void rotateR(struct avlnode * &root)
     28 {
     29     struct avlnode *proot = root;
     30     root = root->lson;
     31     proot->lson = root->rson;
     32     root->rson = proot;
     33     proot->height = max2(height(proot->lson), height(proot->rson)) + 1;
     34     root->height = max2(height(root->lson), height(root->rson)) + 1;
     35 }
     36 
     37 void rotateL(struct avlnode * &root)
     38 {
     39     struct avlnode * proot = root;
     40     root = root->rson;
     41     proot->rson = root->lson;
     42     root->lson = proot;
     43     proot->height = max2(height(proot->lson), height(proot->rson)) + 1;
     44     root->height = max2(height(root->lson), height(root->rson)) + 1;
     45 }
     46 
     47 void rotateRL(struct avlnode * &root)
     48 {
     49     rotateR(root->rson);
     50     rotateL(root);
     51 }
     52 
     53 void rotateLR(struct avlnode * &root)
     54 {
     55     rotateL(root->lson);
     56     rotateR(root);
     57 }
     58 
     59 void insertAVL(struct avlnode * &root, int data)
     60 {
     61     if(root == NULL)
     62     {
     63         root = new struct avlnode;
     64         root->data = data;
     65         root->lson = NULL;
     66         root->rson = NULL;
     67         root->height = 0;
     68         return;
     69     }
     70 
     71     if(data < root->data)
     72     {
     73         insertAVL(root->lson, data);
     74         if(2 == height(root->lson) - height(root->rson))
     75         {
     76             if(data < root->lson->data)
     77                 rotateR(root);
     78             else rotateLR(root);
     79         }
     80     }
     81     else
     82     {
     83         insertAVL(root->rson, data);
     84         if(-2 == height(root->lson) - height(root->rson))
     85         {
     86             if(data > root->rson->data)
     87                 rotateL(root);
     88             else
     89             {
     90                 rotateRL(root);
     91             }
     92         }
     93     }
     94     root->height = max2(height(root->lson), height(root->rson)) + 1;
     95 }
     96 
     97 int main()
     98 {
     99     int N;
    100     scanf("%d", &N);
    101     struct avlnode *root = NULL;
    102     for(int i = 1; i <= N; i++)
    103     {
    104         int data;
    105         scanf("%d", &data);
    106         insertAVL(root,data);
    107     }
    108     printf("%d", root->data);
    109     return 0;
    110 }
    View Code

    pat 1067 Sort with Swap(0,*)                                     本文地址

    首先找出不在正确位置上的数字的个数N,假设每次交换都把一个元素放到了正确的位置则至少需要N-1次交换(最后一次交换把两个元素放到了正确的位置)。

    但是在交换的过程中若0被交换到了第一个位置,那么下一次交换不会把一个元素交换到正确位置,即要做一次额外的交换。因此我们要知道整个过程中0几次被交换到了第一个位置,当输入序列和排序好的序列中存在一个循环时,0就会被交换到第一个位置一次:

    如0 1 2 3 4
       4 0 3 2 1 该序列存在2个循环 0-4-4-1-1-0,2-3-3-2 ,0被交换到了第一个位置2次,但是最后一次是刚好把0归为,因此交换次数为N-1+(2-1)。

    因此最终交换次数是:N-1+循环个数-1

    考虑到一个特殊情况:当0开始就在第一个位置时,我们开始就需要把他交换到某个循环中(和某个不在正确位置的数交换),这样交换次数+1,交换后不在正确位置的元素个数增加了一个,N也需要+1,,即总的交换次数+2。

    代码如下:

     1 #include<cstdio>
     2 int main()
     3 {
     4     int N,*arry;
     5     scanf("%d", &N);
     6     arry = new int[N];
     7     bool *flag = new bool[N];
     8     int swaptimes = -1;
     9     for(int i = 0; i < N; i++)
    10     {
    11         scanf("%d", &arry[i]);
    12         if(arry[i] == i)flag[i] = true;
    13         else
    14         {
    15             flag[i] = false;
    16             swaptimes++;
    17         }
    18     }
    19     if(swaptimes == -1)
    20     {
    21         printf("0");
    22         return 0;
    23     }
    24 
    25     if(flag[0] == true)
    26         swaptimes += 2;
    27     for(int i = 0; i < N; i++)
    28     {
    29         int k = arry[i];
    30         if(flag[k] == false)
    31         {
    32             //找到一个循环
    33             swaptimes++;
    34             while(flag[k] == false)
    35             {
    36                 flag[k] = true;
    37                 k = arry[k];
    38             }
    39         }
    40 
    41     }
    42     printf("%d", swaptimes - 1);
    43     delete []arry;
    44     delete []flag;
    45     return 0;
    46 }
    View Code

    pat 1068 Find More Coins                                       本文地址

    典型的0-1背包问题,关于0-1背包的讲解可参考Cui Tianyi大神的背包九讲

    • 本题动态规划方程:f[i][v] = max{ f[i-1][v],  f[i-1][v-coins[i]]+coins[i] } ,f[i][v]表示前i枚硬币能拼凑出不超过v的最大金额,v代表的是一个金额,coins[i]代表第i个硬币的面额;
    • 由于题目还要求输出最小字典序,可以先对硬币按面值递减排序,并且在程序中,当f[i-1][v] = f[i-1][v-coins[i]]+coins[i] 时,我们选择后者,因为后者倾向于选择排在后面的硬币,越选择排在后面的硬币,结果序列的字典序越小。(开始我误认为先对硬币从小到大排序,然后当f[i-1][v] = f[i-1][v-coins[i]]+coins[i] 时,选择前者也可以得到正确答案,实验证明这是错误的,因为选择前者的意思是倾向于尽量不选择大面值的硬币,但是这样并不等价于结果序列的字典序小,比如2 3 4比1 3 5 的字典序大,但是1 3 5却选择了更大的面值5)
    • 对于最后结果序列的输出,我们用数组path[i][j]保存结果,path[i][j]=true表示凑足价格 j 时,使用了前 i 个硬币中的第 i 个,false表示没有使用,最后可以从path中逆推结果,具体见代码

    代码如下:

     1 #include<cstdio>
     2 #include<algorithm>
     3 
     4 int main()
     5 {
     6     //freopen("input.txt", "r", stdin);
     7     int coinNum, needPay;
     8     scanf("%d%d", &coinNum, &needPay);
     9     int coins[coinNum+1];
    10     for(int i = 1; i <= coinNum; i++)
    11         scanf("%d", &coins[i]);
    12     //f[i][j] 表示前 i 枚硬币能拼凑出的小于等于 j 的最大值(j 这里代表一个价格)
    13     int f[coinNum+1][needPay+1];
    14     //path[i][j]=true表示凑足价格j时,使用了第i个硬币,false表示没有使用
    15     bool path[coinNum+1][needPay+1];
    16     for(int i = 0; i <= coinNum; i++)//初始化
    17         for(int j = 0; j <= needPay; j++)
    18         {
    19             f[i][j] = 0;
    20             path[i][j] = false;
    21         }
    22     std::sort(coins+1, coins+coinNum+1, std::greater<int>());
    23     for(int i = 1; i <= coinNum; i++)
    24         for(int j = coins[i]; j <= needPay; j++)
    25         {
    26             if(f[i-1][j] <= f[i-1][j-coins[i]] + coins[i])
    27             {
    28                 f[i][j] = f[i-1][j-coins[i]] + coins[i];
    29                 path[i][j] = true;
    30             }
    31             else
    32             {
    33                 f[i][j] = f[i-1][j];
    34                 path[i][j] = false;
    35             }
    36         }
    37     if(f[coinNum][needPay] != needPay)
    38         printf("No Solution
    ");
    39     else
    40     {//从path中恢复解
    41         int tmp = needPay, i = coinNum;
    42         while(tmp > 0)
    43         {
    44             if(path[i][tmp] == true)
    45             {
    46                 printf("%d", coins[i]);
    47                 tmp -= coins[i];
    48                 if(tmp > 0)
    49                     printf(" ");
    50             }
    51             i--;
    52         }
    53     }
    54     return 0;
    55 }
    View Code

    对于该题,对于数据规模不大时,可以用递归解法,比如问题 “1...n个硬币凑足价格p” 可以分为 “2...n个硬币凑足价格p-coin[1]” 和"2...n个硬币凑足价格p",即分为第一个硬币选择或者不选两种情。对于结果要求最小字典序,先将硬币按面值从小到大排序,分解问题时,先求第一个硬币选择时的子问题。1068的递归代码如下,但是最后一个测试数据超时,不知道是因为代码有问题还是数据规模太大,如果大家找出了问题,请留言,谢谢!

     1 #include<cstdio>
     2 #include<algorithm>
     3 
     4 bool gatherCoinRecur(int money, int coins[], int n, int start, bool choose[])
     5 {
     6     if(money == 0)return true;
     7     else if(money < 0)return false;
     8     if(start >= n)return false;
     9     choose[start] = true;
    10     if(gatherCoinRecur(money - coins[start], coins, n, start+1, choose))
    11         return true;
    12     choose[start] = false;
    13     if(gatherCoinRecur(money, coins, n, start+1, choose))
    14         return true;
    15     return false;
    16 }
    17 
    18 int main()
    19 {
    20     freopen("input.txt", "r", stdin);
    21     int coinNum, needPay;
    22     scanf("%d%d", &coinNum, &needPay);
    23     int coins[coinNum];
    24     bool choose[coinNum];
    25     for(int i = 0; i < coinNum; i++)
    26     {
    27         scanf("%d", &coins[i]);
    28         choose[i] = false;
    29     }
    30     std::sort(coins, coins+coinNum);
    31     if(gatherCoinRecur(needPay, coins, coinNum, 0, choose))
    32     {
    33         int i = 0;
    34         while(choose[i] == false)i++;
    35         printf("%d", coins[i]);
    36         for(i++; i < coinNum; i++)
    37             if(choose[i])printf(" %d", coins[i]);
    38     }
    39     else printf("No Solution
    ");
    40     return 0;
    41 }
    View Code

     【版权声明】转载请注明出处:http://www.cnblogs.com/TenosDoIt/p/3406776.html

  • 相关阅读:
    etc/ld.so.conf的使用说明
    COM编程入门转发
    OpenCV 中的图像结构IPLImage 和 Qt中QImage之间的转换源代码
    转载Linux启动过程详解2
    Linux添加环境变量与GCC编译器添加INCLUDE与LIB环境变量
    Linux下Opencv+Qt4
    OPENCV 中的图像旋转与缩放
    怎么用qt4绘制橡皮筋直线
    QT4+KDEVELOP+OPENCV配置
    Linux操作系统的头文件和库文件搜索路径
  • 原文地址:https://www.cnblogs.com/TenosDoIt/p/3406776.html
Copyright © 2020-2023  润新知