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

这次老师给我们展开了一次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 

输出样例: 


说明:先花一步从(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;
}

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

2015-8-7 ACM 模拟赛制测试总结 - wenjianwei1 - 算法的设计
 

 这真是一种聪明的作法!所花费的时间非常短,因为不需要那些广搜的复杂操作,只需计算即可。这个方法好像是由苏畅想出来的。

这种方法还可以解决另一道题:一个球从一个桌子的一角弹出,若它能一直弹下去,并给出初始其所经过的一些格子,问在第N次后这个球刚刚经过哪条边(刚刚经过的意思是指,还没有经过到下一条边)?这道题给出了轨迹,接下来的一些模拟也很简单了。具体的解法请看下面这张图:

2015-8-7 ACM 模拟赛制测试总结 - wenjianwei1 - 算法的设计

 


单位 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): 


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

 


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): 



输出(file diff.out): 

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),但这题的数据范围不需要。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值