题解 P1052 【过河】

在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点: 0 , 1 , … , L 0,1,…,L 0,1,,L(其中 L L L是桥的长度)。坐标为 0 0 0 的点表示桥的起点,坐标为 L L L 的点表示桥的终点。青蛙从桥的起点开始,不停的向终点方向跳跃。一次跳跃的距离是 S S S T T T 之间的任意正整数(包括 S , T S,T S,T)。当青蛙跳到或跳过坐标为 L L L 的点时,就算青蛙已经跳出了独木桥。

题目给出独木桥的长度LL,青蛙跳跃的距离范围S,TS,T,桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。

显然是 d p dp dp,是用 S T L STL STL当中的 m a p map map可以做到30分

#include <bits/stdc++.h>//万能头文件
using namespace std;
int l,n,s,t;
map<int,bool>m;//记有没有石头
map<int,int>dp;//最少踩到石头的个数
int main(){
    cin>>l>>s>>t>>n;
    for(int i=1;i<=n;i++){
        int x;
        cin>>x;
        m[x]=true;
    }
    for(int i=1;i<=l+t-1;i++){
    	dp[i]=INT_MAX/2;
    	for(int j=s;j<=t&&j<=i;j++)dp[i]=min(dp[i],dp[i-j]);//倒退
    	if(m[i])dp[i]++;
	}int s=dp[l];
	for(int i=l+1;i<=l+t-1;i++)s=min(s,dp[i]);
	cout<<s;
    return 0;
}

之后,我们该想一想如何 A C AC AC这道题

我们发现石头数量很少,而独木桥却很长

360截图18141224304435.png

遇到这张图,我们可能还会选择暴力的方法

360截图170405117195111.png

但是遇到这张图,你还会用暴力吗?

空的地方就是随便走就行了,完全可以不用老老实实的去看,我们可以把路径压缩,更简单地说就是如果后面的一个石头与前面的一个石头距离太远,我们可以把后面一个石头推到前一个石头附近,至于这个量是多少呢,需要自己把握。

我自己还是觉得稍微保险一点,不要 T L E TLE TLE就行了,所以我选择把这个数定在 1000 1000 1000,当然听同学说,他定的比较小也过了,这并没有关系。

所以,我们可以看代码了

#include<bits/stdc++.h>
using namespace std;
int l,s,t,m,a[110],dp[100010],b[110];
bool x[100010];
int main(){
    cin>>l;
    cin>>s>>t>>m;
    for(int i=1;i<=m;i++)cin>>a[i];
    sort(a+1,a+1+m);
    if(s==t){//这个应该很简单,我上面没有说
        int ans=0;
        for(int i=1;i<=m;i++)
            if(a[i]%s==0)ans++;//如果会经过它,答案+1
        cout<<ans;//输出
        return 0;
    }
    for(int i=1;i<=m;i++)
        if(a[i]-a[i-1]>1000)b[i]=b[i-1]+1000;//注意啦,如果原来的距离小于1000,你要保持不变
        else b[i]=a[i]-a[i-1]+b[i-1];
	for(int i=1;i<=m;i++)x[b[i]]=true;//石头
	l=b[m];
    for(int i=1;i<=l+t-1;i++){
    	dp[i]=INT_MAX/2;
    	for(int j=s;j<=t&&j<=i;j++)dp[i]=min(dp[i],dp[i-j]);//转移状态
    	if(x[i])dp[i]++;
	}int ans=dp[l];
	for(int i=l;i<=l+t-1;i++)ans=min(ans,dp[i]);//打擂法求最小值
	cout<<ans;//输出
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
过河卒是一个典型的动态规划问题。首先,我们将整个棋盘看作一个二维数组,数组的每个元素表示到达该位置的路径数目。然后,我们根据题目给出的条件,逐步更新数组中的元素,直到计算出到达目标位置的路径数目。 具体的解题思路如下: 1. 首先,我们可以将马的位置设置为0,表示无法经过该位置。 2. 然后,我们根据马的位置,更新数组中的元素。对于二维数组中的每个位置,我们根据左边和上边的位置来计算到达当前位置的路径数目。具体地,如果左边和上边的位置都可以经过,那么到达当前位置的路径数目就等于左边和上边位置的路径数目之和。如果左边或上边的位置无法经过,那么到达当前位置的路径数目就等于左边或上边位置的路径数目。 3. 最后,我们输出目标位置的路径数目。 下面是洛谷p1002过河题解C++代码: ```cpp #include <bits/stdc++.h> using namespace std; int main() { long long a[21][21]; int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; // 初始化数组,马的位置设置为0 for(int i=0; i<=20; i++) { for(int k=0; k<=20; k++) { a[i][k] = 1; } } a[x2][y2] = 0; // 根据马的位置更新数组中的元素 if(x2 >= 2 && y2 >= 1) a[x2-2][y2-1] = 0; if(x2 >= 1 && y2 >= 2) a[x2-1][y2-2] = 0; if(x2 <= 18 && y2 >= 1) a[x2+2][y2-1] = 0; if(x2 <= 19 && y2 >= 2) a[x2+1][y2-2] = 0; if(x2 >= 2) a[x2-2][y2+1] = 0; if(x2 >= 1) a[x2-1][y2+2] = 0; if(y2 >= 1) a[x2+2][y2-1] = 0; if(y2 >= 2) a[x2+1][y2-2] = 0; // 动态规划计算路径数目 for(int i=1; i<=20; i++) { for(int k=1; k<=20; k++) { if(a[i][k] != 0) { a[i][k] = a[i-1][k] + a[i][k-1]; } } } // 输出目标位置的路径数目 cout << a[x1][y1] << endl; return 0; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值