P1052 过河(状态压缩)

P1052 过河(状态压缩)

题目描述

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

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

输入输出格式

输入格式:

输入文件river.in的第一行有一个正整数L(1 <= L <= 10^9),表示独木桥的长度。第二行有三个正整数S,T,M,分别表示青蛙一次跳跃的最小距离,最大距离,及桥上石子的个数,其中1 <= S <= T <= 10,1 <= M <= 100。第三行有M个不同的正整数分别表示这M个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。所有相邻的整数之间用一个空格隔开。

输出格式:

输出文件river.out只包括一个整数,表示青蛙过河最少需要踩到的石子数。

输入输出样例

输入样例#1:

10
2 3 5
2 3 5 6 7

输出样例#1:

2

说明

对于30%的数据,L \le 10000L≤10000;

对于全部的数据,L \le 10^9L≤10?9??。

2005提高组第二题

分析:

很经典的一道题,也是很著名的一道状态压缩DP。

这道题的思路理解之后其实也是蛮简单的,就是因为L太大,1e9时空都会超,又因为n<100,是一个稀疏图,所以呢,可以对他进行路径压缩,我们可以认为中间的点都是大跳过去的,所以对于长了很多的路程就去取模啊,模一模,单车变摩托。

我们用 f[i]表示在数轴的 i 点时所能踩石子的最少个数

那么很容易得出状态转移方程:

j表示跳的步长

if(i点有石子) f[i]=min(f[i],f[i-j]+1)

else
f[i]=min(f[i],f[i-j])

在数轴很长的情况下,那么我们就压缩一下

先把石子位置(用数组a来存放)从小到大排序,计算两两石子间的距离(用数组d来存放),如果距离<=t,那么a[i]=a[i-1]+d[i]

如果距离大于t,那么就需要压缩距离了,即 a[i]=a[i-1]+t+(d[i]%t)

然后还有要注意的两点

1.它的石子没说是已经排好序的,所以我们需要排序。

2.注意取p的范围,就是要在压缩的路程后面加一个t,因为不一定最后一个点刚好是石头最少的(因为最佳答案不一定恰好到终点),可能是p+1,p+2,所以要从它转移过来,你应该循环到p+t。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<string>
 6 #define min(a,b) (a>b?b:a)
 7 using namespace std;
 8 int l,p,dp[10000],stone[200],a[10000],s,k[200],d[200],t,m,n,b[10000];
 9 int main()
10 {
11 //  freopen("std.in","r",stdin);
12     cin>>l>>s>>t>>n;
13     for (int i=1;i<=n;i++)
14     cin>>stone[i];
15     stone[0]=0;
16     a[0]=0;
17     sort(stone+1,stone+n+1);//排序
18     for (int i=1;i<=n;i++)
19     {
20         d[i]=stone[i]-stone[i-1];//取两石子间的距离
21         k[i]=d[i]%t;//对距离取模以压缩路径
22         if (d[i]<=t+k[i])
23         a[i]=a[i-1]+d[i];//a为压缩后的路径
24         else a[i]=a[i-1]+t+k[i];
25         //b[a[i]]数组对有石子的位置进行标记
26         b[a[i]]=1;//对石子进行标记
27     }
28     p=a[n]+t+(l-a[n])%t;//终点
29     memset(dp,0x7f,sizeof(dp));
30     dp[0]=0;
31     for (int i=1;i<=p+t-1;i++)
32         for (int j=s;j<=t;j++)//dp过程
33         {
34             if (i-j>=0&&i-j<p)
35             {
36                 if (b[i])
37                 dp[i]=min(dp[i-j]+1,dp[i]);
38                 else
39                 dp[i]=min(dp[i-j],dp[i]);
40             }
41         }
42     int mx=200;
43     for (int i=p;i<=p+t-1;i++)//寻找答案,在p与p+t-1之间
44     mx=min(mx,dp[i]);
45     cout<<mx;
46     return 0;
47 }
时间: 2024-10-22 10:36:50

P1052 过河(状态压缩)的相关文章

NOIP2005过河[DP 状态压缩]

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

洛谷P1052 过河 动态规划

洛谷P1052 过河通过观察可以发现 这个点很稀疏 dp 有很长一段距离都是没有用的,那么我们可以采用离散化的思想 把这个距离压缩,但同时还要保证 对答案没有影响 如果 s==t 这时候我们需要特判 只要判断 pos[ i ] % s == 0 就可以知道是否踩到石子 然后因为 最多青蛙一次只跳了 10 假如 s == 9 t == 10 如果两个石子间的距离大于100 我们每次也可以 一步步的慢慢调整 ,其实总共只有10个状态,%10==1 %10==2 %10==3 然后我们就可以把距离 >

Attack on Titan(状态压缩)

Attack on Titan WL大神最近迷上了一款名叫<神话时代>的游戏,这个游戏里有一种非常强力的兵种--泰坦,可以不费吹灰之力地摧毁一座座村庄.但是,泰坦有一个弱点,就是不能过河.有一次,WL大神玩了一个布满河流的地图,这个地图上坐落着N个村庄,M条河流(每条河流都可以视作一条横跨地图的直线).WL大神一口气使用"TITANOMACHY"秘籍在一些地点共召唤了K个泰坦.现在,WL大神想知道都有哪些村庄可以被摧毁. Input 输入数据有多组. 第一行输入一个整数T(

胜利大逃亡(续)(状态压缩bfs)

胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7357    Accepted Submission(s): 2552 Problem Description Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)……这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带

uva 818(dfs+图+状态压缩)

题意:有n个环,编号从1到n,给出了一些环环相扣的情况,比如给a和b表示a和b两个环的扣在一起的,每个环都是可以打开的,问最少打开多少个环,然后再扣好,可以让所有的环成为一条链. 题解:状态压缩把所有的打开环的情况枚举出来,然后拿去判断是否成立,更新打开环后的图g[i][j],和每个点的度数,不成立有三种情况,1.计算没有打开的环的度数,如果大于2说明不会有链,2.把没有打开环拿去dfs,访问过就vis[i]++,如果vis[i]>=2说明存在环,3.如果打开的环数num + 1小于链的数量,说

POJ 3254 Corn Fields 状态压缩DP (C++/Java)

http://poj.org/problem?id=3254 题目大意: 一个农民有n行m列的地方,每个格子用1代表可以种草地,而0不可以.放牛只能在有草地的,但是相邻的草地不能同时放牛, 问总共有多少种方法. 思路: 状态压缩的DP. 可以用二进制数字来表示放牧情况并判断该状态是否满足条件. 这题的限制条件有两个: 1.草地限制. 2.相邻限制. 对于草地限制,因为输入的时候1是可以种草地的. 以"11110"草地分析,就只有最后一个是不可以种草的.取反后得00001  .(为啥取反

uva 11195 Another queen (用状态压缩解决N后问题)

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2136 Problem A Another n-Queen Problem I guess the n-queen problem is known by every person who has studied backtracking. In this problem you s

dp状态压缩

dp状态压缩 动态规划本来就很抽象,状态的设定和状态的转移都不好把握,而状态压缩的动态规划解决的就是那种状态很多,不容易用一般的方法表示的动态规划问题,这个就更加的难于把握了.难点在于以下几个方面:状态怎么压缩?压缩后怎么表示?怎么转移?是否具有最优子结构?是否满足后效性?涉及到一些位运算的操作,虽然比较抽象,但本质还是动态规划.找准动态规划几个方面的问题,深刻理解动态规划的原理,开动脑筋思考问题.这才是掌握动态规划的关键. 动态规划最关键的要处理的问题就是位运算的操作,容易出错,状态的设计也直

HDU3001(KB2-J 状态压缩dp)

Travelling Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8103    Accepted Submission(s): 2642 Problem Description After coding so many days,Mr Acmer wants to have a good rest.So travelling is