分治总结2

问题 B: 【分治】Babelfish

题目

You have just moved from Waterloo to a big city. The people here speak an incomprehensible dialect of a foreign language. Fortunately, you have a dictionary to help you understand them.

输入

Input consists of up to 100,000 dictionary entries, followed by a blank line, followed by a message of up to 100,000 words. Each dictionary entry is a line containing an English word, followed by a space and a foreign language word. No foreign word appears more than once in the dictionary. The message is a sequence of words in the foreign language, one word on each line. Each word in the input is a sequence of at most 10 lowercase letters.

输出

Output is the message translated to English, one word per line. Foreign words not in the dictionary should be translated as “eh”.
代码

#include <iostream>
#include <map>
#include <cstdio>
using namespace std;

map<string,string>m;///即使是string到string的映射,char[]型的也可以使用

int main()
{
   
    char from[100],to[100],ori[100],target[100];
    while(cin.getline(ori,100)&&ori[0]!='\0')///ori[0]是不等于\0不是\n
    {
   
        sscanf(ori,"%s %s",to,from);///注意sscanf的用法
        m[from]=to;///char[]到char[]的映射
    }
    while(~scanf("%s",target))
    {
   
        if(m.find(target)!=m.end())
            cout<<m[target]<<'\n';
        else
            cout<<"eh"<<'\n';
    }
}

问题 C: 【分治】魔法石的诱惑

题目

修罗王远远地看见邪狼狂奔而来,问道:“慌慌张张地跑什么?” 邪狼大口大口地喘气:“我路过一家魔法石店,看到摆着那么多高阶魔法石,我就跑进去抢了一大袋。” 修罗王怒道:“光天化日,朗朗乾坤,众目睽睽之下,你也敢抢?” 邪狼:“我抢魔法石的时候,压根儿就没看见人,眼里只看见魔法石了。” 修罗王:“……” 其实邪狼的贪婪很容易理解,因为高阶魔法石有一个特征,即它的重量进行阶乘运算后末尾有几个0,就拥有同等重量普通魔法石几倍的魔法力。例如5!=5×4×3×2×1=120,而120结尾包含1个零,这意味着该魔法石拥有同等重量的普通的魔法石1倍的魔法力。你的任务是找到最小自然数N,使N!在十进制下包含Q个零。

输入

一个数Q(0≤Q≤108)

输出

如果无解,输出“No solution”,否则输出N。

代码

#include <iostream>
#include <map>
#include <cstdio>
using namespace std;

int get0(int x)///获取0的个数
{
   
    int bit=5,cnt=0;
    while(bit<=x)
    {
   
        cnt+=x/bit;
        bit*=5;
    }
    return cnt;
}
int solve(int x)///二分求解
{
   
    int l=1,r=1e9;
    while(r>l)///不可带等号,因为下面有r=mid
    {
   
        int mid=(l+r)/2;
        if(get0(mid)>x) r=mid-1;
        else if(get0(mid)<x) l=mid+1;
        else r=mid;///0的个数等于x了,那么使r=mid,在区间[l,mid]中找,因为要求最小的r
        ///例子:若x=4,r=24,r!也有4个0,但是r不是最小的,20才是
    }
    return r;
}
int main()
{
   
    int x;cin>>x;
    if(x==0)///0!=1
    {
   
        cout<<0<<endl;
        return 0;
    }
    int ans=solve(x);
    if(get0(ans)!=x) cout<<"No solution"<<endl;///个数不相符,无解
    else cout<<ans<<endl;
}

题目:

The FORTH programming language does not support floating-point arithmetic at all. Its author, Chuck Moore, maintains that floating-point calculations are too slow and most of the time can be emulated by integers with proper scaling. For example, to calculate the area of the circle with the radius R he suggests to use formula like R * R * 355 / 113, which is in fact surprisingly accurate. The value of 355 / 113 ≈ 3.141593 is approximating the value of PI with the absolute error of only about 2*10-7. You are to find the best integer approximation of a given floating-point number A within a given integer limit L. That is, to find such two integers N and D (1 <= N, D <= L) that the value of absolute error |A - N / D| is minimal.

输入

The first line of input contains a floating-point number A (0.1 <= A < 10) with the precision of up to 15 decimal digits. The second line contains the integer limit L. (1 <= L <= 100000).

输出

Output file must contain two integers, N and D, separated by space.

思路:
追赶法求解,cmp为输入的目标值,maxn为最大的分子分母的上限,temp=cmp-i/j,Abs为temp的绝对值,minn为Abs的最小值,初始化为1000000000;
1)temp>0时,说明i/j不够大,i++,i/j追赶cmp
2)temp<0时,i/j太大,j++,缩小i/j与cmp的距离
3)Abs>minn时,更新minn,p,q
当i,j其中一个大于maxn时停止;

#include <iostream>
#include <map>
#include <cstdio>
#include <cmath>
using namespace std;
int maxn;
int p,q;
void solve(double cmp)
{
   
    int i=1,j=1;
    double minn=10000000;
    while(i<=maxn&&j<=maxn)
    {
   
        double temp=cmp-i*1.0/j;
        double Abs=abs(temp);
        if(Abs<minn)
        {
   
            minn=Abs;
            p=i,q=j;
        }
        if(temp>0) i++;
        else j++;
    }
}
int main()
{
   
    double cmp;
    cin>>cmp>>maxn;
    solve(cmp);
    cout<<p<<' '<<q<<endl;
}


问题 E: 【分治】逃亡

题目:

邪狼紧张地说:“老大,警察快追过来了,我们快逃跑吧!”
修罗王傲然道:“在我的字典里没有逃跑。。。”
邪狼内心崇敬地想:“老大实在是太有领袖范了……”
修罗王接着说:“只有战略转移。”
邪狼:“……”
现在,修罗王和邪狼两人需要从A地出发尽快到达B地。出发时A地有一辆可带一人的自动驾驶悬浮车。又知两人步行速度相同。问怎样利用小车才能使两人尽快同时到达B地。

输入

有三个int类型整数,分别表示A、B两地的距离,步行速度和车速。

输出

有一个小数位数为2的浮点数,即最短时间。
思路
二分第一次车走的距离,如何分别求出两个人到达的时间,当两个近乎相等时,返回时间

#include <iostream>
#include <map>
#include <cstdio>
#include <cmath>
using namespace std;

double solve(double s,double a,double b)
{
   
    double l=0,r=s,t1,t2;
    while(l<=r)
    {
   
        double mid=(l+r)/2;
        t1=mid/b+(s-mid)/a;
        t2=mid/b+(mid-mid/b*a)/(a+b)+(s-(mid-mid/b*a)/(a
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
分治算法是一种把问题分成多个子问题,然后将子问题的解合并起来得到原问题解的算法。通常情况下,分治算法可以分为三个步骤:分解、解决和合并。在本次实验中,我们将使用分治算法来解决一个经典的问题:求解一个数组中的最大值。 1.问题描述 给定一个数组,我们需要找到其中的最大值。 2.算法设计 我们使用分治算法来解决这个问题。具体来,我们将数组分成两个子数组,然后递归地对这两个子数组求解最大值,最后将两个子数组的最大值合并起来得到原数组的最大值。 具体的算法步骤如下: (1)将数组分成两个子数组,分别求解其中的最大值。 (2)将两个子数组的最大值进行比较,得到原数组的最大值。 3.实验过程 为了实现这个算法,我们需要编写一个递归函数。该函数将在不断地对子数组进行分解,直到子数组的长度为1时,返回子数组中的唯一元素。 在进行合并时,我们需要比较两个子数组的最大值,然后将较大的值作为结果返回。 下面是具体的代码实现: ``` // 分治算法求解最大值 int max(int arr[], int start, int end) { // 如果子数组长度为1,返回该元素 if (start == end) { return arr[start]; } // 将数组分成两个子数组 int mid = (start + end) / 2; int left = max(arr, start, mid); int right = max(arr, mid + 1, end); // 合并两个子数组的结果 return left > right ? left : right; } ``` 4.实验结果 我们使用一个长度为10的随机数组进行测试,如下所示: ``` int arr[] = {9, 4, 7, 8, 6, 2, 10, 3, 5, 1}; int result = max(arr, 0, 9); cout << "The max value in the array is " << result << endl; ``` 运行结果如下: ``` The max value in the array is 10 ``` 可以看到,我们成功地使用分治算法求解了给定数组的最大值。 5.实验总结 本次实验我们学习了分治算法的基本思想,并且使用分治算法成功地求解了一个经典问题。分治算法可以解决很多复杂的问题,例如排序、查找等,它的时间复杂度通常可以达到O(nlogn)。因此,在算法设计中,我们可以考虑使用分治算法来解决一些复杂的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值