pat 1065 A+B and C                                         

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

 #include<cstdio>
#include<climits>
#include<cmath>
//double精度为15~16位,不能满足精度要求
int main()
{
int testNum;
scanf("%d",&testNum);
long long MAX = LONG_LONG_MAX; //pow(2,63) - 1,
long long MIN = LONG_LONG_MIN; //-1*pow(2,63);
for(int i = ; i <= testNum; i++)
{
long long a,b,c;
scanf("%lld %lld %lld", &a, &b, &c); if(a >= && b >=)
{
if(MAX - a >= b)
goto NORMAL;
else
{
printf("Case #%d: true\n", i);
continue;
}
}
else if(a < && b < )
{
if(MIN - a <= b)
goto NORMAL;
else
{
printf("Case #%d: false\n", i);
continue;
}
}
else ; NORMAL:
if(a + b > c)
printf("Case #%d: true\n", i);
else
printf("Case #%d: false\n", i);
}
return ;
}

pat 1066 Root of AVL Tree                                          本文地址

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

 #include<cstdio>
#include<climits>
#include<cmath> //operate of AVL tree inline int max2(int a, int b)
{
return a>b? a:b;
} struct avlnode
{
struct avlnode *rson;
struct avlnode *lson;
int data;
int height;
}; inline int height(struct avlnode *tree)
{
if(NULL == tree)
return -;
else return tree->height;
} void rotateR(struct avlnode * &root)
{
struct avlnode *proot = root;
root = root->lson;
proot->lson = root->rson;
root->rson = proot;
proot->height = max2(height(proot->lson), height(proot->rson)) + ;
root->height = max2(height(root->lson), height(root->rson)) + ;
} void rotateL(struct avlnode * &root)
{
struct avlnode * proot = root;
root = root->rson;
proot->rson = root->lson;
root->lson = proot;
proot->height = max2(height(proot->lson), height(proot->rson)) + ;
root->height = max2(height(root->lson), height(root->rson)) + ;
} void rotateRL(struct avlnode * &root)
{
rotateR(root->rson);
rotateL(root);
} void rotateLR(struct avlnode * &root)
{
rotateL(root->lson);
rotateR(root);
} void insertAVL(struct avlnode * &root, int data)
{
if(root == NULL)
{
root = new struct avlnode;
root->data = data;
root->lson = NULL;
root->rson = NULL;
root->height = ;
return;
} if(data < root->data)
{
insertAVL(root->lson, data);
if( == height(root->lson) - height(root->rson))
{
if(data < root->lson->data)
rotateR(root);
else rotateLR(root);
}
}
else
{
insertAVL(root->rson, data);
if(- == height(root->lson) - height(root->rson))
{
if(data > root->rson->data)
rotateL(root);
else
{
rotateRL(root);
}
}
}
root->height = max2(height(root->lson), height(root->rson)) + ;
} int main()
{
int N;
scanf("%d", &N);
struct avlnode *root = NULL;
for(int i = ; i <= N; i++)
{
int data;
scanf("%d", &data);
insertAVL(root,data);
}
printf("%d", root->data);
return ;
}

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。

代码如下:

 #include<cstdio>
int main()
{
int N,*arry;
scanf("%d", &N);
arry = new int[N];
bool *flag = new bool[N];
int swaptimes = -;
for(int i = ; i < N; i++)
{
scanf("%d", &arry[i]);
if(arry[i] == i)flag[i] = true;
else
{
flag[i] = false;
swaptimes++;
}
}
if(swaptimes == -)
{
printf("");
return ;
} if(flag[] == true)
swaptimes += ;
for(int i = ; i < N; i++)
{
int k = arry[i];
if(flag[k] == false)
{
//找到一个循环
swaptimes++;
while(flag[k] == false)
{
flag[k] = true;
k = arry[k];
}
} }
printf("%d", swaptimes - );
delete []arry;
delete []flag;
return ;
}

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中逆推结果,具体见代码

代码如下:

 #include<cstdio>
#include<algorithm> int main()
{
//freopen("input.txt", "r", stdin);
int coinNum, needPay;
scanf("%d%d", &coinNum, &needPay);
int coins[coinNum+];
for(int i = ; i <= coinNum; i++)
scanf("%d", &coins[i]);
//f[i][j] 表示前 i 枚硬币能拼凑出的小于等于 j 的最大值(j 这里代表一个价格)
int f[coinNum+][needPay+];
//path[i][j]=true表示凑足价格j时,使用了第i个硬币,false表示没有使用
bool path[coinNum+][needPay+];
for(int i = ; i <= coinNum; i++)//初始化
for(int j = ; j <= needPay; j++)
{
f[i][j] = ;
path[i][j] = false;
}
std::sort(coins+, coins+coinNum+, std::greater<int>());
for(int i = ; i <= coinNum; i++)
for(int j = coins[i]; j <= needPay; j++)
{
if(f[i-][j] <= f[i-][j-coins[i]] + coins[i])
{
f[i][j] = f[i-][j-coins[i]] + coins[i];
path[i][j] = true;
}
else
{
f[i][j] = f[i-][j];
path[i][j] = false;
}
}
if(f[coinNum][needPay] != needPay)
printf("No Solution\n");
else
{//从path中恢复解
int tmp = needPay, i = coinNum;
while(tmp > )
{
if(path[i][tmp] == true)
{
printf("%d", coins[i]);
tmp -= coins[i];
if(tmp > )
printf(" ");
}
i--;
}
}
return ;
}

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

 #include<cstdio>
#include<algorithm> bool gatherCoinRecur(int money, int coins[], int n, int start, bool choose[])
{
if(money == )return true;
else if(money < )return false;
if(start >= n)return false;
choose[start] = true;
if(gatherCoinRecur(money - coins[start], coins, n, start+, choose))
return true;
choose[start] = false;
if(gatherCoinRecur(money, coins, n, start+, choose))
return true;
return false;
} int main()
{
freopen("input.txt", "r", stdin);
int coinNum, needPay;
scanf("%d%d", &coinNum, &needPay);
int coins[coinNum];
bool choose[coinNum];
for(int i = ; i < coinNum; i++)
{
scanf("%d", &coins[i]);
choose[i] = false;
}
std::sort(coins, coins+coinNum);
if(gatherCoinRecur(needPay, coins, coinNum, , choose))
{
int i = ;
while(choose[i] == false)i++;
printf("%d", coins[i]);
for(i++; i < coinNum; i++)
if(choose[i])printf(" %d", coins[i]);
}
else printf("No Solution\n");
return ;
}

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

PAT 1065 1066 1067 1068的更多相关文章

  1. PAT甲级1066. Root of AVL Tree

    PAT甲级1066. Root of AVL Tree 题意: 构造AVL树,返回root点val. 思路: 了解AVL树的基本性质. AVL树 ac代码: C++ // pat1066.cpp : ...

  2. PAT 1065 - 1068 题解

    这次的题目来源是 2013 年 10 月 7 日下午的浙大计算机研究生招生机试题. 这次题目的难度,按姥姥的说法是:『比普通的 PAT 要难了 0.5 个点.我是把自己的题目从 1.0 到 5.0 以 ...

  3. PAT 1065 A+B and C (64bit) (20)

    1065. A+B and C (64bit) (20) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 HOU, Qiming G ...

  4. PAT 1065 A+B and C (64bit)

    1065 A+B and C (64bit) (20 分)   Given three integers A, B and C in [−], you are supposed to tell whe ...

  5. PAT 乙级 1066 图像过滤(15) C++版

    1066. 图像过滤(15) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 图像过滤是把图像中不重要的像素都染成 ...

  6. PAT甲题题解-1068. Find More Coins (30)-dp,01背包

    一开始没多想,虽然注意到数据N<=10^4的范围,想PAT的应该不会超时吧,就理所当然地用dfs做了,结果最后一组真的超时了.剪枝啥的还是过不了,就意识到肯定不是用dfs做了.直到看到别人说用0 ...

  7. PAT 1065 单身狗(25)(STL-map+思路+测试点分析)

    1065 单身狗(25 分) "单身狗"是中文对于单身人士的一种爱称.本题请你从上万人的大型派对中找出落单的客人,以便给予特殊关爱. 输入格式: 输入第一行给出一个正整数 N(≤  ...

  8. PAT 1065 A+B and C[大数运算][溢出]

    1065 A+B and C (64bit)(20 分) Given three integers A, B and C in [−2​63​​,2​63​​], you are supposed t ...

  9. pat 甲级 1066. Root of AVL Tree (25)

    1066. Root of AVL Tree (25) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue An A ...

随机推荐

  1. WordPress主题开发:开启侧边栏小工具功能

    步骤一:在主题的functions.php中,添加一段代码,开启侧边栏功能,代码如下: <?php //参数 $args = array( 'name' => __( '主侧边栏'), ' ...

  2. linux内核netfilter模块分析之:HOOKs点的注册及调用

    转自;http://blog.csdn.net/suiyuan19840208/article/details/19684883 -1: 为什么要写这个东西?最近在找工作,之前netfilter 这一 ...

  3. 新闻编辑室第一季/全集The Newsroom迅雷下载

    第一季 The Newsroom Season 1 (2012)看点:频出佳剧的HBO这次将目光对准了新闻间这个话题多,故事更多的“小”地方.该剧讲述的是一家虚构的有线电视新闻网ACN的故事,由阿伦· ...

  4. Java并发编程的艺术(九)——批量获取多条线程的执行结果

    当向线程池提交callable任务后,我们可能需要一次性获取所有返回结果,有三种处理方法. 方法一:自己维护返回结果 // 创建一个线程池 ExecutorService executorServic ...

  5. 用Handler的post()方法来传递线程中的代码段到主线程中执行

    自定义的线程中是不能更新UI的,但是如果遇到更新UI的事情,我们可以用handler的post()方法来将更新UI的方法体,直接传送到主线程中,这样就能直接更新UI了.Handler的post()方法 ...

  6. Logstash使用jdbc_input同步Mysql数据时遇到的空时间SQLException问题

    今天在使用Logstash的jdbc_input插件同步Mysql数据时,本来应该能搜索出10条数据,结果在Elasticsearch中只看到了4条,终端中只给出了如下信息 [2017-08-25T1 ...

  7. JavaScript中的方法、方法引用和参数

    首先,我们来看一段代码,如果觉得不甚明白的,则本文会对你有益: var player = function (e) {             return (function f(m) {      ...

  8. MySQL中的information_schema数据库表说明

    MySQL 中的 information_schema 数据库   版权声明:https://blog.csdn.net/kikajack/article/details/80065753 1. 概述 ...

  9. C# 程序设置开机启动(一)

    一.示例使用VBScript创建启动文件,并添加到Windows系统的启动目录 默认情况下 所有用户启动目录:C:\ProgramData\Microsoft\Windows\Start Menu\P ...

  10. 使用模拟对象(Mock Object)技术进行测试驱动开发

    敏捷开发 敏捷软件开发又称敏捷开发,是一种从上世纪 90 年代开始引起开发人员注意的新型软件开发方法.和传统瀑布式开发方法对比,敏捷开发强调的是在几周或者几个月很短的时间周期,完成相对较小功能,并交付 ...