两个思维
Posted wwq-19990526
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了两个思维相关的知识,希望对你有一定的参考价值。
1:HDU 5122 K.Bro Sorting
题目描述:输入T,代表T组样例,每组样例输入n代表n个数,要求进行操作,使n个数为升序排列,求最少操作的次数。
进行的操作为:对于任意一个数来说,如果它大于等于它右边的数,则交换两数的位置,直到小于右边的数或者到了数组尾部。比如2 5 4 1 3,对第一个数进行操作后,发现顺序不变,依然为2 5 4 1 3,接下来对第二个数进行操作,操作后的顺序为2 4 1 3 5,接下来对第三个数操作,操作后的顺序为2 1 3 4 5,最后再对第一个数进行操作便为1 2 3 4 5。
思路:为了找到最小操作数,则必须每一个操作的数都一步到位,比如刚刚的例子对于2这个数我们进行了2次操作,虽然第一次为无效操作。
思维:我们可以按照冒泡的思维来想这题,从数组的后面往前看,当后一个数比前面一个数小时,就进行一次操作,两个数调换,小的就到了前面,大的往后面冒,而且后面都是冒泡好了的序列,所以大数每次往后面冒的时候都会冒到正确的位子,当后一个数比前面一个数小时,此时不用进行操作,只要更新最小值,因为下一次操作比最小值大的数会正确冒到相应位置。
ac代码(数据有点大要用c输入):
#include<iostream> #include<cstdio> using namespace std; int a[1000005]; int main() { int T,n,num; while(~scanf("%d",&T)) { num=0; while(T--) { int ans=0,min; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&a[i]); min=a[n-1]; for(int i=n-2;i>=0;i--) { if(min<a[i]) ans++; else min=a[i]; } printf("Case #%d: %d\n",++num,ans); } } return 0; }
2:HDU 5037 Frog
题目描述:在一条长为M的小河里有N个石头,一只每次能够跳L米远的青蛙要过河,现在你可以在河中任意添加石头让青蛙过河,问在青蛙使用最优策略的前提下跳到对岸最多需要多少次?
输入描述:有T组样例,每组样例先输入N,M,L。在接下来的N行里,每行一个数,代表距离起始岸多少距离处有石头。
思路:因为青蛙会使用最优策略,故不能每隔1m就添加石头,此时青蛙最多跳(M+L-1)/L次,要想青蛙跳的次数多,我们可以发现,如果两岸距离L+1时,青蛙就得跳两次。所以我们可以将已有的每两个石头之间分成两个部分,一个是距离没有(L+1)的部分(x)和距离有y倍(L+1)的部分,所以无论如何,青蛙在(L+1)部分都要跳两次,总共则会跳2*y次,而在x部分,因为青蛙会选择最优策略,则需要看
ac代码(数据有点大要用c输入):
#include<iostream> #include<algorithm> #include<cstdio> using namespace std; int main() { int T; while(~scanf("%d",&T)) { int N,M,L,num=0; int a[200005]; while(T--) { scanf("%d %d %d",&N,&M,&L); for(int i=1;i<=N;i++) scanf("%d",&a[i]); a[0]=0;a[N+1]=M; sort(a,a+N+2); int ans=0,x,y,d=L; for(int i=1;i<=N+1;i++) { x=(a[i]-a[i-1])%(L+1); y=(a[i]-a[i-1])/(L+1); if(d+x>L) { ans=ans+2*y+1; d=x; } else { ans=ans+2*y; d+=x; } } printf("Case #%d: %d\n",++num,ans); } } return 0; }
以上是关于两个思维的主要内容,如果未能解决你的问题,请参考以下文章
Android 使用两个不同的代码片段获取当前位置 NULL
结合两个代码片段?将用户输入的 Youtube url 转换为嵌入 url,然后将 iframe src 替换为转换后的 url