主题:[讨论]第76次编程比赛结果讨论
mht@ [专家分:1260] 发布于 2008-11-09 13:15:00
比赛贴已经结了!
至于结果,还没出来,我会尽快的.
我把题目贴过来,大家可以讨论讨论
一、过河问题
问题描述:
在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点:0,1,……,L(其中L是桥的长度)。坐标为0的点表示桥的起点,坐标为L的点表示桥的终点。青蛙从桥的起点开始,不停的向终点方向跳跃。一次跳跃的距离是S到T之间的任意正整数(包括S,T)。当青蛙跳到或跳过坐标为L的点时,就算青蛙已经跳出了独木桥。
题目给出独木桥的长度L,青蛙跳跃的距离范围S,T,桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。
输入:
第一行有一个正整数L(1 <= L <=10^9),表示独木桥的长度。第二行有三个正整数S,T,M,分别表示青蛙一次跳跃的最小距离,最大距离,及桥上石子的个数,其中1 <= S <= T <= 10,1 <= M <= 100。第三行有M个不同的正整数分别表示这M个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。所有相邻的整数之间用一个空格隔开。
输出:
只包括一个整数,表示青蛙过河最少需要踩到的石子数。
样例输入:
10
2 3 5
2 3 5 6 7
样例输出:
2
二、南极冰山问题
传说中,南极有一片广阔的冰原,在冰原下藏有史前文明的遗址。整个冰原被横竖划分成了很多个大小相等的方格。在这个冰原上有N个大小不等的矩形冰山,这些巨大的冰山有着和南极一样古老的历史,每个矩形冰山至少占据一个方格,且其必定完整地占据方格。冰山和冰山之间不会重叠,也不会有边或点相连。
ACM探险队在经过多年准备之后决定在这个冰原上寻找遗址。根据他们掌握的资料,在这个冰原上一个大小为一格的深洞中,藏有一个由史前人类制作的开关。而唯一可以打开这个开关的是一个占据接近一格的可移动的小冰块。显然,在南极是不可能有这样小的独立冰块的,所以这块冰块也一定是史前文明的产物。他们在想办法把这个冰块推到洞里去,这样就可以打开一条通往冰原底部的通道,发掘史前文明的秘密。冰块的起始位置与深洞的位置均不和任何冰山相邻。
这个冰原上的冰面和冰山都是完全光滑的,轻轻的推动冰块就可以使这个冰块向前滑行,直到撞到一座冰山就在它的边上停下来。冰块可以穿过冰面上所有没有冰山的区域,也可以从两座冰山之间穿过。冰块只能沿网格方向推动。
输入
输入文件第一行为冰山的个数N (1<=N<=4000),第二行为冰块开始所在的方格坐标X1,Y1,第三行为深洞所在的方格坐标X2,Y2,以下N行每行有四个数,分别是每个冰山所占的格子左上角和右下角坐标Xi1,Yi1,Xi2,Yi2 (坐标都在int 型范围内即 -2^31到2^31)
输出
输出文件仅包含一个整数,为最少推动冰块的次数。如果无法将冰块推入深洞中,则输出0。
样例输入
2
1 1
5 5
1 3 3 3
6 2 8 4
样例输出
3
另外,我没找到测试数据,谁有可以贴上来
如果没有,只能自己做几个,比较少
回复列表 (共17个回复)
沙发
mht@ [专家分:1260] 发布于 2008-11-09 17:52:00
自己做的测试数据,很少,不全面,大家可以自己试试,
过河问题:
测试1: // 原题题目给出的,估计都过了
10
2 3 5
2 3 5 6 7
结果:
2
*********************
测试2:
100000000 // 把数写大,测试一下算法效率
2 3 10
2 3 45 56 678 3456 5678 6789 45678 345678
结果:
1
********************
测试3: // 这个算法不好的,要8、9秒以上,好的瞬间出
100000000
2 3 10
2 3 5 6 7 100 5678 6789 45678 345678
结果:
2
测试4: // 测试是否对石子排序
10
2 3 5
7 6 2 3 5
结果:
3
***************************************************************
***************************************************************
冰山问题;
测试1: // 原题目已给出
2
1 1
5 5
1 3 3 3
6 2 8 4
结果:
3
**********************
测试2: // 测试坐标范围是否全面
5
1 -1
-2 1
2 -1 2 0
-1 -3 1 -3
-4 -3 -4 -1
-4 3 -2 3
3 2 3 3
结果;
5
********************
测试3: // 不可达到目标,输出0,我贴上的程序,没有按要求,我是输出的Error!!!
1
1 1
5 5
1 3 3 3
结果:
0
*******************
测试4: // 测试极端情况
2
1 -1
-2 1
-100000001 -2 -100000000 -1
-100000001 100000000 -99999999,100000001
结果:
0
板凳
fenix124 [专家分:70] 发布于 2008-11-10 10:19:00
之前的不知道怎么答案为5的那个出不来。。。今天修改了一些地方的坐标影射方式,又好了。
3 楼
雨中飞燕 [专家分:18980] 发布于 2008-11-11 13:37:00
难道LZ是手工测的吗?
4 楼
mht@ [专家分:1260] 发布于 2008-11-11 14:27:00
呵呵,是的。
提交的代码,一般都没有全部通过的,虽然就这几组
我还要在研究研究在飞燕onlinejudge上下的那个测试系统,还没搞定,试了几次都不行
5 楼
倚楼看楼 [专家分:30] 发布于 2008-11-12 11:33:00
不好意思啊,我这个菜鸟想提一点小要求,就是请各位高手给出代码时可否略作一些
注释呢?否则对于我这样的新而又真心想学的人来说,理解有些困难,拜托了。
不好意思加谢谢。
6 楼
kachan [专家分:30] 发布于 2008-11-12 21:22:00
样例输入:
10
2 3 5
2 3 5 6 7
样例输出:
2
这样计算第一次0跳到去3,再3跳去6,再跳也去不到10啊????是不是有点问题解释一下还是我理解错??
7 楼
mht@ [专家分:1260] 发布于 2008-11-12 21:47:00
ls没有看清题目啊
输出的是最少踩到的石子数,不是几次跳过去
这是我写的程序,现在贴上来吧,不知道对不对
#include <iostream>
using namespace std;
int F_min(int* dp,int D_min,int D_max)
{
int min=0x7fffffff;
for(int i=D_min;i<=D_max;i++)
{
min=min<dp[i]?min:dp[i];
}
return min;
}
int main()
{
int L_bridge,D_min,D_max,S_num;
int *dp; // 窗口数组
int *Bridge;
int Menkan;
int Min;
// 输入数据————————————————————————————
cout<<"请输入桥的长度L_bridge:"<<endl;
cin>>L_bridge;
cout<<"请输入跳跃的最小距离D_min、跳跃的最大距离D_max、石子的个数S_num:"<<endl;
cin>>D_min>>D_max>>S_num;
//开辟空间—————————————————————————————
Bridge=new int[S_num];
for(int i=0;i<S_num;i++)
cin>>Bridge[i];
//D_min , D_max相等的情况——————————————————————
if(D_min==D_max)
{
int counter=0;
for(i=0;i<S_num;i++)
if(Bridge[i]%D_min==0)
counter++;
cout<<"最少踩到的石子数为:"<<endl;
cout<<counter;
exit(0);
}
//对石子的位子排序————————————————————————————
int temp;
for(i=0;i<S_num-1;i++)
for(int k=i+1;k<S_num;k++)
if(Bridge[k]<Bridge[i])
{
temp=Bridge[k];
Bridge[k]=Bridge[i];
Bridge[i]=temp;
}
dp=new int[D_max+2];
Menkan=D_min*D_min/(D_max-D_min)+D_max+1; //?
Min=D_max+1;
for(i=0;i<D_max+2;i++)
dp[i]=0;
//D_min,D_max不等的情况求最优解————————————————————
int j,k;
for(j=S_num,i=L_bridge;i>=0;)
{
//if(i=-1) break;
int D;
if(j<1) D=i;
else D=i-Bridge[j-1];
if(D>=Menkan)
{
for(k=0;k<=D_max;k++)
dp[k]=dp[Min];
i=Bridge[j-1];
continue;
}
if(D==0&&i!=0)
{
dp[0]=1+F_min(dp,D_min,D_max);
for(k=D_max+1;k>0;k--)
dp[k]=dp[k-1];
dp[Min]=F_min(dp,1,D_max);
i--;
j--;
continue;
}
if(D<Menkan)
{
dp[0]=F_min(dp,D_min,D_max);
for(k=D_max+1;k>0;k--)
dp[k]=dp[k-1];
dp[Min]=F_min(dp,1,D_max);
i--;
continue;
}
}
cout<<"最少踩到的石子数为:"<<endl;
cout<<dp[0];
return 0;
}
对于这个问题的压缩,我是压缩到 D_max大小,就是跳跃的最大距离
上计算机网络的时候,看到一个滑动窗口,就类比着
先定义一个D_max大小的数组,作为一个窗口,从桥尾向前滑动,并检测下一个石子的位置,若大于
“门槛”,就将窗口一直移到石子前一格处
这样对空间的要求不大
8 楼
wwdlk [专家分:10] 发布于 2008-11-13 20:11:00
7楼能不能加点注释,我是新手,看算法没有注释很累的
9 楼
kachan [专家分:30] 发布于 2008-11-13 22:59:00
输出的是最少踩到的石子数,不是几次跳过去
那我跳一次不就是踩到一个石子吗.头和尾都没石的
样例输入:
10
2 3 5 ///这里最小距离是2..最大距离是3,,,有5个石
2 3 5 6 7//头是0尾是10中间有石2,3,5,6,7
样例输出:
2 //那最后结果不是3吗????/
10 楼
mht@ [专家分:1260] 发布于 2008-11-14 18:49:00
不知ls是怎么理解的啊!!你认真看看题目,最少是2次
举个2次的例子给你看看
0->2->4->6->8->10
跳了5次,其中2和6踩到石子,
所以就是两次了
我来回复