1.均分纸牌
题目描述
有 NNN 堆纸牌,编号分别为 1,2,…,N1,2,…,N1,2,…,N 。每堆上有若干张,但纸牌总数必为 NNN 的倍数。可以在任一堆上取若干张纸牌,然后移动。
移牌规则为:在编号为 111 堆上取的纸牌,只能移到编号为 222 的堆上;在编号为 NNN 的堆上取的纸牌,只能移到编号为 N−1N-1N−1 的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。
现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。
例如 N=4N=4N=4 , 444 堆纸牌数分别为:
① 999 ② 888 ③ 171717 ④ 666
移动 333 次可达到目的:
从 ③ 取 444 张牌放到 ④ ( 9,8,13,109,8,13,109,8,13,10 )-> 从 ③ 取 333 张牌放到 ②( 9,11,10,109,11,10,109,11,10,10 )-> 从 ② 取 111 张牌放到①( 10,10,10,1010,10,10,1010,10,10,10 )。
输入输出格式
输入格式:
两行
第一行为: NNN ( NNN 堆纸牌, 1≤N≤1001 \le N \le 1001≤N≤100 )
第二行为: A1,A2,…,AnA_1,A_2, … ,A_nA1,A2,…,An ( NNN 堆纸牌,每堆纸牌初始数, l≤Ai≤10000l \le A_i \le 10000l≤Ai≤10000 )
输出格式:
一行:即所有堆均达到相等时的最少移动次数。
特别好理解的。是一个很典型的贪心算法。这个题应该想到用每个数都减去平均张数,题目就变成了要移动的数量。正数表示要移走,负数表示要移过来。如果本来就有0张怎么办呢?那么就要有过滤这个步骤了。
while(a[i]==0&&i<n)i++;//过滤掉左边的0 while(a[j]==0&&j>1)j--;//过滤掉右边的
当然在移牌过程中也不能忘记过滤每个过程中产生的0牌。
while(a[i]==0&&i<j) i++;
那么代码如下
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int ave,n,a[110]; int main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>a[i];ave+=a[i]; } ave=ave/n; for(int i=1;i<=n;i++) a[i]-=ave; int i=1,j=n; int step; while(a[i]==0&&i<n)i++; while(a[j]==0&&j>1)j--; while(i<j){ a[i+1]+=a[i]; a[i]=0; step++,i++; while(a[i]==0&&i<j) i++; } cout<<step; }
用for循环写的版本如下
#include<iostream> using namespace std; int n,w,i,j,a[10010],step; int main(){ cin>>n; for(i=1;i<=n;i++){ cin>>a[i];w+=a[i]; } w/=n; for(i=1;i<=n;i++) a[i]-=w; i=1;j=n; for(i=1;i<=n;i++){ if(a[i]!=0){ a[i+1]+=a[i]; a[i]=0; step++; } } cout<<step; }
2.迷宫和走迷宫(我也不知道这是一个什么顺序了做着玩吧)
迷宫就直接贴代码就好了,反正就是裸的dfs
#include<iostream> #include<cstdio> using namespace std; int n,m,t,sx,sy,fx,fy,sum=0; int flag[101][101],trap1,trap2; void search(int i,int j){ if(i==fx&&j==fy){ sum++; return; } else { flag[i][j]=1; if((j!=m)&&(flag[i][j+1]==0)) search(i,j+1),flag[i][j+1]=0;//you if((i!=n)&&(flag[i+1][j]==0)) search(i+1,j),flag[i+1][j]=0;//xia if((i!=1)&&(flag[i-1][j]==0)) search(i-1,j),flag[i-1][j]=0;//shang if((j!=1)&&(flag[i][j-1]==0)) search(i,j-1),flag[i][j-1]=0;//zuo } } int main(){ cin>>n>>m>>t; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ flag[i][j]=0;} cin>>sx>>sy>>fx>>fy; for(int i=1;i<=t;i++){ cin>>trap1>>trap2; flag[trap1][trap2]=1; } search(sx,sy); cout<<sum; }
走迷宫就比迷宫多一个输出路径的操作
注意优先级:左上右下
设置一个bool变量pd来判断有没有路径。用一个step来记录步数。
#include<iostream> #include<cstdio> #include<cmath> using namespace std; int m,n,a[16][16]; int a1[1001],b1[1001]; int bix,biy,enx,eny; bool pd; void read(){ cin>>m>>n; for(int i=1;i<=m;i++) for(int j=1;j<=n;j++){ cin>>a[i][j]; } cin>>bix>>biy; cin>>enx>>eny; } void print(int p){ pd=1; for(int i=0;i<p;i++){ cout<<"("<<a1[i]<<","<<b1[i]<<")->"; } cout<<"("<<enx<<","<<eny<<")"; cout<<endl; } void search(int x,int y,int step){ if (x < 1 || y < 1 || x>m || y>n) return; if(x==enx&&y==eny){ print(step); return; } if(a[x][y]==1){ a1[step]=x;b1[step]=y; a[x][y]=0; search(x,y-1,step+1); search(x-1,y,step+1); search(x,y+1,step+1); search(x+1,y,step+1); a[x][y]=1; } } int main(){ read(); search(bix,biy,0); if(pd==0) cout<<"-1"; }
3.跳石头
题目背景
一年一度的“跳石头”比赛又要开始了!
题目描述
这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 NNN 块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。
为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 MMM 块岩石(不能移走起点和终点的岩石)。
输入输出格式
输入格式:
第一行包含三个整数 L,N,ML,N,ML,N,M ,分别表示起点到终点的距离,起点和终点之间的岩石数,以及组委会至多移走的岩石数。保证 L≥1L \geq 1L≥1 且 N≥M≥0N \geq M \geq 0N≥M≥0 。
接下来 NNN 行,每行一个整数,第 iii 行的整数 Di(0<Di<L)D_i( 0 < D_i < L)Di(0<Di<L) , 表示第 iii 块岩石与起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同一个位置。
输出格式:
一个整数,即最短跳跃距离的最大值。
典型的二分题。二分查找,需要写一个judge函数,来判断移走的个数。若是移走的个数符合要求,记录下来,再搜索其他的是否符合要求,输出最合适的值。
// luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int l,n,m,a[1000010],i,sum=0,mid; int s,e; bool judge(int x){ int time=0; int i=0; int now=0; while(i<n+1){ i++; if(a[i]-a[now]<x){ time++; } else now=i; } if(time>m) return false; else return true; } int main(){ cin>>l>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; a[n+1]=l;s=1;e=l; while(s<=e){ mid=(s+e)/2; if(judge(mid)){ sum=mid; s=mid+1; } else e=mid-1; } cout<<sum<<endl; }