您的位置:首页 > 其它

2015-8-7 ACM 模拟赛制测试总结

2016-02-15 19:35 267 查看
这次老师给我们展开了一次ACM赛制的测试,只不过题目少很多,每组的人数也多一些,不过那些题都还蛮难的。我们小组做了三题,和其他组几乎一样,也就是那些水题吧~不过有一些人做了一些难题但却没有做水题,正所谓有得必有失吧。
这次的题目出自USACO,下面是解题报告:

地理 geo

Time Limit:10000MS Memory Limit:65536K

Total Submit:26 Accepted:15
Description
奶牛们刚学习完地理课,知道地球是个球。他们非常震惊,满脑子都是球形。他们试图把地球表面看成一个NxN (1 <= N <= 100)的方格,但是顶端连接着底部、左边连接到右边。格子用坐标表示,左下角坐标为(1,1)。

例如: N=5时,牛从(1,3)位置向下走会到(5,3);从(2,5)向右走会到(2,1)位置。牛可以上、下、左、右和斜线方向走。

如果按照牛的模型,请计算依次行走 M(1 <= M <= 100) 格子的最短路径。

输入格式(file geo.in):

第一行:两个整数: N M。

下面M行:表示依次要行走的格子坐标:r c。

输出格式(file geo.out):

最少行走步数。

输入样例:

5 3

1 1

5 5

3 5

输出样例:

3

说明:先花一步从(1,1)走到(5,5),再花两步从(5,5)走到(3,5)。

#include <stdio.h>
#include <algorithm>
using namespace std;

int main()
{
int N, M;
int len = 0;
int x=-1, y=-1;
scanf("%d %d", &N, &M);
for(int i = 0;i<M;i++)
{
int nx, ny;
scanf("%d %d", &ny, &nx);
ny--;nx--;
if(x >= 0)
{
int moves = max(min(abs(nx-x),N-abs(nx-x)),
min(abs(ny-y),N-abs(ny-y)));
len += moves;
}
x = nx;y = ny;
}

printf("%d\n", len);
return 0;
}

这道题很简单主要的解题方法就是宽度优先搜索(或广度优先搜索),但是却有另外一个更好的方法,速度大大提高。



这真是一种聪明的作法!所花费的时间非常短,因为不需要那些广搜的复杂操作,只需计算即可。这个方法好像是由苏畅想出来的。
这种方法还可以解决另一道题:一个球从一个桌子的一角弹出,若它能一直弹下去,并给出初始其所经过的一些格子,问在第N次后这个球刚刚经过哪条边(刚刚经过的意思是指,还没有经过到下一条边)?这道题给出了轨迹,接下来的一些模拟也很简单了。具体的解法请看下面这张图:



单位 unit

Time Limit:10000MS Memory Limit:65536K

Total Submit:31 Accepted:7
Description
某星球上有很多计量系统,之间的计量单位的转换很繁琐。希望你能编程解决这个问题。

现有N (1 <= N <= 100) 个转换关系(比如:12 A 等于 1 B, 3 B等于 1 C等等 ),请计算指定的M (1 <= M <= 100) 个转换关系(比如:多少 A 等于 1 C).

输入格式( unit.in )

第一行:两个整数 N 和 M。

下面N行:每行有3个值:A S1 S2,A是一个小数,S1、S2是两个单词,它们之间用空格分开。表示 A 个 S1 等于 1个S2.

再后面有M行:每行两个单词 X Y,中间用空格分开,请你计算出1个Y相当于多少X。

输出格式 (file unit.out):

共M行:每行对应一个输入数据中的单位转换问题。答案为乘1000之后的四舍五入取整。保证答案不超过2^31.

样例输入:

4 1

12 inch foot

3 foot yard

5280 foot mile

0.0254 meter inch

meter mile

样例输出:

1609344
#define in cin
#define out cout
#include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
#include <map>
#include <string>

using namespace std;

static map<string, int> no;
static int pool = 0;

static int getno(const string &a)
{
if (!no.count(a)) no[a] = pool++;
return no[a];
}

int main()
{
int N, M;
double ratio[200][200];

in >> N >> M;
for (int i = 0; i < 200; i++)
for (int j = 0; j < 200; j++)
ratio[i][j] = (i == j) ? 1.0 : HUGE_VAL;
for (int i = 0; i < N; i++)
{
double r;
string x, y;
in >> r >> x >> y;
int nx = getno(x);
int ny = getno(y);
ratio[nx][ny] = r;
ratio[ny][nx] = 1.0 / r;
}

for (int y = 0; y < pool; y++)
for (int x = 0; x < pool; x++)
if (ratio[x][y] != HUGE_VAL)
for (int z = 0; z < pool; z++)
if (ratio[y][z] != HUGE_VAL && ratio[x][z] == HUGE_VAL)
ratio[x][z] = ratio[x][y] * ratio[y][z];

for (int i = 0; i < M; i++)
{
string x, y;
in >> x >> y;
out << (int) round(1000.0 * ratio[getno(x)][getno(y)]) << "\n";
}
return 0;
}


这题仍然可以用广搜做。把那些转换的信息抽象成一个图中的链接,再用广搜一下子就好了。但是我觉得这个问题要求效率的话应该用像Dijkstra之类的多源最短路径算法,这样显然就能快很多。特别是在以后一些同样是单位转换,但走两条路得到的数量可能有所不同的情况下,最短路径显然改一下就好了。举个例子,假设美元汇人民币为1:6,人民币汇澳门币为1:2,而美元直接汇澳币为1:11,则这种情况下显然是先汇人民币再汇澳币划算。

问题 nroots

Time Limit:10000MS Memory Limit:65536K

Total Submit:31 Accepted:6
Description
一些牛在花园中工作---让他们考虑根,根的乘方是很容易.那些牛是考虑很大的根.

给整数 N(1<=N<=10^25) and K (3<=K<=10)计算整数B,N=B^K;

问题名:nroots

输入文件:

第一行:两个分开的整数:N 和 K

样例输入:

8072216216 3

样例输出:

2006

输出解释:

2006^3=8072216216
好吧,这题的正解是二分,但是却有人用了pow函数来水分……而且还水对了……原理是这样的:假如有一个数a,要开n次方,则可以证明a的1/n次方等于a的n次方根!
所以,只需用pow(N,1/K)就可以了。但是要注意的一点是,int无法存储像N这样25位的数,但我们却可以用long double来存储,虽然空间大了,但精度同时也高了不少!只不过,其实这道题的数据出的还是很仁慈的,根据标准,好像还是可以装得下的。

但是最好的方法应该还是牛顿迭代法,代码就先不给出了。

Problem dictcow

Time Limit:10000MS Memory Limit:65536K

Total Submit:6 Accepted:3
Description
奶牛们有他们自己的字典,包含W(1 <= W <=600)个单词,每个单词包含不超过25个字母,

‘a’~‘z’,牛会接受到一个字符串S,长度L不大于300,因为牛发音不准,要删除

部分字母,使字符串可以由牛的字典中的单词组成,请你删去最少个数的字母,

使得字符串由字典中的单词组成。

PROBLEM NAME: dictcow

输入

* 第一行:两个整数: W 和 L

* 第二行:字符串S

* 3到.W+2 行:字典单词,每行一个

SAMPLE INPUT (file dictcow.in):

6 10

browndcodw

cow

milk

white

black

brown

farmer

输出

一行,输出最小删除的数

* SAMPLE OUTPUT (file dictcow.out):

2

这题不难,一个动规即可,但是主要是要找准动规的方式,本题的动规方法就是不断的在已知可以放入的字符串(可以通过删除得到的)后面不断地添加相应的单词,最后找出最大值即可。

Problem m2o

Time Limit:10000MS Memory Limit:65536K

Total Submit:40 Accepted:33
Description
奶牛们正在实验压缩算法,他们被那些在网上找到的好像压缩过的文本所吸引。他们相信一些用网络的人将连续的相同的字母用一个数字代替,这个数字表示连续的相同的字母的个数

例如 L33TSP34K 是

LTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTSPKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK的缩写

帮助奶牛们写一个程序,给出的文本用最多80个大写字母组成,用奶牛的运算法则将他们压缩

PROBLEM NAME: m2o

INPUT FORMAT:

第一行:最多80个大写字母组成的文本

SAMPLE INPUT (file m2o.in):

LTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTSPKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK

OUTPUT FORMAT:

一行:压缩后的文本

SAMPLE OUTPUT (file m2o.out):

L33TSP34K
这题一看就是水题,我们组一次就AC了。原理不用讲了,主要就是要注意只有1个的时候不用压缩。这种方法很类似于DOS时代的一种图片压缩算法RLE,非常简单。

Problem diff

Time Limit:10000MS Memory Limit:65536K

Total Submit:65 Accepted:34
Description
给你两个整数 A 和 B (1 <= A <= 10^75, 1 <= B <=10^75), 求A与B的差 D (D = A - B). D 的范围保证在 -100,000..100,000.

PROBLEM NAME: diff

INPUT FORMAT:

* 第一行: 整数 A.

* 第二行: 整数 B

输入 (file diff.in):

3

2

输出(file diff.out):

1

OUTPUT DETAILS:

3-2 = 1.

这题也是非常之水的一道题,简简单单一个高精度就过了。不用多讲。但是老师好像说有一种不用高精度的方法。首先,注意到D的范围很小,只有正负十万。加起来也就二十万。所以,我们可以用枚举,枚举这二十万,离超时还远着呢。那么,我们枚举,用什么来算?用高精度加法吗?不对,因为D很小,所以,我们只需要看A和B的后六位就行了。这样,连枚举都省了!直接将后六位转成两个整数然后相减即可,用string输入,再用int存储,最后直接输出。就像真的A-B一样简单。这就是一个问题化简的方法,寻找题目中的漏洞,再用巧妙的方法击破。这样的速度显然快很多,不需要那样死算了,但是数据范围变大时可能就不行了。所以也要细心。

Problem Pen

Time Limit:10000MS Memory Limit:65536K

Total Submit:26 Accepted:8
Description
问题描述:

奶牛们正在学习写字.因为它们的蹄子太大,所以用的笔很重,导致它们写出来的句子中间没有空格.

现在FJ想知道奶牛们写了什么. 给出一个奶牛们写的句子(最多含有80个字符) 和一部奶牛字典(最多含有1000个单词) , 请根据字典中的单词给奶牛写的句子中间加上空格,使

句子中所有单词都在字典中出现, 假如有多种加空格的方法, 只输出"ambiguous" (保证最少有一种加空格的方法).

PROBLEM NAME: pen

输入说明

* 第一行: 奶牛们写的句子(最多包含80个字符

* 第二行: 一个数字N(N<=1000), 表示字典中有几个单词

第3~N+2行: 每行输入一个单词,表示字典中出现的单词.单词长度不超过10。

输出说明:

输出一个句子,即加空格后的句子,如有多种方法,只输出"ambiguous".

SAMPLE INPUT (file pen.in):

THESEPENSSUREAREHEAVY

14

ARE

BARN

FARMER

HEAVY

IS

JOHN

LIGHT

MILK

MOO

PENS

SURE

THESE

UNDER

USACO

SAMPLE OUTPUT (file pen.out):

THESE PENS SURE ARE HEAVY

这题其实就是一个完全背包,要求有且仅有这一种可能性。最简单的方法,直接暴力求解,时间复杂度为O(10^3*1000),基本上就是用四个嵌套的循环从第一个字符开始,枚举每一个单词,看看能不能放进去,如果能则更新当前的剩余字符串。但是如果用一下哈希,那可能会好很多,时间复杂度基本降到了O(10^2),但这题的数据范围不需要。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: