传送门:A. Alena's Schedule (简单模拟)
题意:给你n个数,表示这个人的课程有则为1,没课则为0,每当他有课的接下来没课的时候,他就要回家
他回家有个条件,就是有课之后最少是连续两次没课,他才可以回家,否则要在学校等待有课,最后输出他在学校呆的时间。
思路:将有课的下标先记录下来,直接比较两者的距离,用总时间减掉回家的时间 ,要注意开头和结尾都会有空课,也要减去。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[110];
int vis[110];
int n;
int main(){
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
while(~scanf("%d",&n)){
memset(vis,0,sizeof(vis));
int cnt=0;
for(int i=1 ; i<=n ; i++){
scanf("%d",&a[i]);
if(a[i])vis[cnt++]=i;
}
int ans=vis[0]-1+(n-vis[cnt-1]);
for(int i=1 ; i<cnt ; i++){
if(vis[i]-vis[i-1]>2){
ans+=vis[i]-vis[i-1]-1;
}
}
if(cnt==0)ans=n;
printf("%d\n",n-ans);
}
return 0;
}
传送门:B. Laurenty and Shop (暴力)
题意:Laurenty要从右下角的地方走到左上角,再从左上角的地方走到右下角。每条路都有等待时间,每次走只能穿越中间的那条马路一次,而且来回不能穿越相同的马路。
思路:不需要用最短路或者搜索,n<=50。。。数据小而且图形特殊,直接暴力就好了,搞一个前缀和和后缀和,再加上中间的那条路的时间,比较一下最小值。
#include <bits/stdc++.h>
#define ll __int64
using namespace std;
const int inf=0x3f3f3f3f;
int n,a[55],b[55],c[55];
int main(){
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
while(~scanf("%d",&n)){
a[1]=b[1]=0;
for(int i=2 ; i<=n ;i++){
cin>>a[i];
a[i]+=a[i-1];
}
for(int i=2 ; i<=n ;i++){
cin>>b[i];
b[i]+=b[i-1];
}
for(int i=1 ; i<=n ; i++){
cin>>c[i];
}
int sum=inf;
for(int i=1 ; i<=n-1 ;i++){
for(int j=i+1 ; j<=n ;j++){
int cost1=a[i]+c[i]+b[n]-b[i];
int cost2=a[j]+c[j]+b[n]-b[j];
if(sum>cost1+cost2){
sum=cost1+cost2;
}
}
}
printf("%d\n",sum);
}
return 0;
}
传送门:C. Gennady the Dentist (暴力 模拟)
题意:一群小朋友排队去看牙医,当一个小朋友进到牙医办公室内开始拔牙时,会哭,哭声为vi分贝,后面的小朋友听到了办公室传来的哭声,勇气值会降低vi - <当前小朋友在队伍的位置 - 1>,当在外面等待的小朋友的勇气值小于零,他就会开始哭,然后在他之后的所有小朋友都会被影响,从而勇气值降低di,并且这个小朋友会直接离开队伍,回家找妈妈。初始给出小朋友的数量,以及每个小朋友的vi,di,初始勇气值pi问,最后能有那些小朋友可以进入牙医办公室。输出升序。
思路:直接暴力。注意:被吓哭的小朋友会马上离开队列。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Child{
ll v,d,p;
}c[4005];
int ans[4005],n,cnt=0;
int main(){
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
scanf("%d",&n);
for(int i=1 ; i<=n ;i++){
scanf("%lld %lld %lld",&c[i].v,&c[i].d,&c[i].p);
}
for(int i=1 ;i<=n ; i++){
if(c[i].p>=0){
ans[cnt++]=i;
ll tmp,sum=0;
tmp=c[i].v;
for(int j=i+1 ; j<=n ;j++){
if(c[j].p<0) continue;
c[j].p-=tmp+sum;
tmp--;
if(tmp<0)tmp=0;
if(c[j].p<0) sum+=c[j].d;
}
}
}
printf("%d\n",cnt);
printf("%d",ans[0]);
for(int i=1 ; i<cnt ;i++){
printf(" %d",ans[i]);
}
printf("\n");
return 0;
}
传送门:D. Phillip and Trains (BFS)
题意:
3∗(N<=100)的网格,有个人要逃跑,他每次先向右移动一格,然后可以上下一格或者不动,然后车移动2格
问能否从右边界逃跑分析:
bfs就好了,转移就向右,然后上下不动三种,车移动2格,可以根据相对运动,人直接再右移动两格就好了,这两格都要判断一下~
#include <bits/stdc++.h> #define ll __int64 using namespace std; typedef pair<int,int>P; char a[4][105]; int t,n,k,sx; bool bfs(int sx){ queue<P>q; q.push(P(sx,1)); while(q.size()){ int x=q.front().first,y=q.front().second;q.pop(); if(isalpha(a[x][++y]))continue; if(y>=n)return true; for(int i=-1 ; i<=1 ; i++){ int nx=x+i; if(nx>3||nx<1)continue; if(isalpha(a[nx][y])||isalpha(a[nx][y+1]) ||isalpha(a[nx][y+2])||a[nx][y+2]==1)//如果a[nx][y+2]已经到达过 continue; int ny=y+2; if(ny>=n)return true; a[nx][ny]=1; q.push(P(nx,ny)); } } return false; } int main(){ // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); scanf("%d",&t); while(t--){ memset(a,0,sizeof(a)); scanf("%d %d",&n,&k); for(int i=1 ; i<=3 ; i++){ scanf("%s",a[i]+1); if(a[i][1]=='s')sx=i; } puts(bfs(sx)?"YES":"NO"); } return 0; }
小结:做了很多套CF div.2之后发现一般前三题未必一定是纯算法题,大部分是考一些思维以及细节处理,不要思维定势