A - 必做题 - 1
Sample Input
5
1 3 2 3 3
11
1 1 1 1 1 5 5 5 5 5 5
7
1 1 1 1 1 1 1
Sample Output
3
5
1
解题思路
排序后,所有相同的数都挨在一起
记录当前数的个数,当个数大于(n+1)/2时输出
每个数只遍历一次,复杂度为On
代码实现
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int Max = 1e6+ 100;
int n;
int a[Max];
int flag;
int sum;
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<n;i++)
{
// cin>>a[i];
scanf("%d",&a[i]);
}
sort(a,a+n);
flag = a[0];
sum=1;
int m = (n+1)/2;
for(int i=1;i<n;i++)
{
if(flag==a[i])
sum++;
else
{
sum=1;
flag=a[i];
}
if(sum>=m)
{
// cout<<a[i]<<endl;
printf("%d\n",a[i]);
break;
}
}
}
return 0;
}
B - 必做题 - 2
Sample Input
3 4 5
S....
.###.
.##..
###.#
#####
#####
##.##
##...
#####
#####
#.###
####E
1 3 3
S##
#E#
###
0 0 0
Sample Output
Escaped in 11 minute(s).
Trapped!
解题思路
三维数组的bfs
不能移动到有#的,和已经移动过了的地方
用bfs而不用dfs,因为dfs不能保证求出来的是最优解
步数和记忆化用vis记录
具体实现看代码
代码
#include<cstdio>
#include<queue>
#include<cstring>
#include<iostream>
using namespace std;
int l,r,c;
char a[35][35][35];
int vis[35][35][35];
int res;
struct point{
int _i,_j,_k; //层,行,列
};
point start,end; //记录起点和终点的位置
queue<point> q;
void ini();
void bfs();
int main()
{
while(1)
{
scanf("%d%d%d",&l,&r,&c);
if(l==0&&r==0&&c==0) return 0;
for(int i=0;i<l;i++)
{
for(int j=0;j<r;j++)
{
for(int k=0;k<c;k++)
{
cin>>a[i][j][k];
if(a[i][j][k]=='S')
start._i=i,start._j=j,start._k=k;
if(a[i][j][k]=='E')
end._i=i,end._j=j,end._k=k;
}
}
}
bfs();
if(vis[end._i][end._j][end._k]>1) printf("Escaped in %d minute(s).\n",vis[end._i][end._j][end._k]-1);
if(vis[end._i][end._j][end._k]<=1) printf("Trapped!\n");
ini();
}
return 0;
}
void ini() //初始化
{
memset(a,0,sizeof(a));
memset(vis,0,sizeof(vis));
while(!q.empty()) q.pop();
}
void bfs()
{
int i=start._i,j=start._j,k=start._k;
vis[i][j][k] = 1;
q.push(start);
while(!q.empty())
{
point p=q.front();
q.pop();
if(p._i==end._i&&p._j==end._j&&p._k==end._k) return ; //到达终点结束
for(int qi=0;qi<6;qi++) //上下左右前后
{
point pt;
if(qi==0) //上
{
if(p._i+1 < l && vis[p._i+1][p._j][p._k]==0 && a[p._i+1][p._j][p._k]!='#')
{
vis[p._i+1][p._j][p._k] = vis[p._i][p._j][p._k]+1;
pt._i = p._i+1,pt._j=p._j,pt._k=p._k;
q.push(pt);
continue;
}
else continue;
}
if(qi==1) //下
{
if(p._i-1 >= 0 && vis[p._i-1][p._j][p._k]==0 && a[p._i-1][p._j][p._k]!='#')
{
vis[p._i-1][p._j][p._k] = vis[p._i][p._j][p._k]+1;
pt._i = p._i-1,pt._j=p._j,pt._k=p._k;
q.push(pt);
continue;
}
else continue;
}
if(qi==2) //右
{
if(p._k+1 < c && vis[p._i][p._j][p._k+1]==0 && a[p._i][p._j][p._k+1]!='#')
{
vis[p._i][p._j][p._k+1] = vis[p._i][p._j][p._k]+1;
pt._i = p._i,pt._j=p._j,pt._k=p._k+1;
q.push(pt);
continue;
}
else continue;
}
if(qi==3) //左
{
if(p._k-1 >= 0 && vis[p._i][p._j][p._k-1]==0 && a[p._i][p._j][p._k-1]!='#')
{
vis[p._i][p._j][p._k-1] = vis[p._i][p._j][p._k]+1;
pt._i = p._i,pt._j=p._j,pt._k=p._k-1;
q.push(pt);
continue;
}
else continue;
}
if(qi==4) //前
{
if(p._j-1 >= 0 && vis[p._i][p._j-1][p._k]==0 && a[p._i][p._j-1][p._k]!='#')
{
vis[p._i][p._j-1][p._k] = vis[p._i][p._j][p._k]+1;
pt._i = p._i,pt._j=p._j-1,pt._k=p._k;
q.push(pt);
continue;
}
else continue;
}
if(qi==5) //后
{
if(p._j+1 < r && vis[p._i][p._j+1][p._k]==0 && a[p._i][p._j+1][p._k]!='#')
{
vis[p._i][p._j+1][p._k] = vis[p._i][p._j][p._k]+1;
pt._i = p._i,pt._j=p._j+1,pt._k=p._k;
q.push(pt);
continue;
}
else continue;
}
}
}
return ;
}
C - 必做题 - 3
Sample Input
1 3 1 2 3
2 6 -1 4 -2 3 -2 3
Sample Output
6
8
Hint
数据量很大,需要scanf读入和dp处理。
解题思路
动态规划问题
状态设置 dp[i][j] -----选了j的,分成i段的最大值
状态转移方程 dp[i][j] = max(dp[i-1][j-1] ,dp[i-1][k]) + a[j]
解释: 状态是选择了j的,所以转移到 dp[i][j]必须要加上 a[j]
分为2种情况:
第一种,a[j]是连着a[j-1]的那一段的
第二种, a[j]是新开的一段,与a[k]有间隔
由上述2种状态转移过来
但是,数据量太大,会爆内存,所以要使用滚动数组
设置一个max1[] 记录上一次的结果
dp[]用来计算这一次的结果
从 i=1滚动到 m 结束,得到的就是分成m段的结果
max1[j-1]是不包括j-1,j-1之前的最大值
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1e6+5;
int m,n;
int a[N];
int dp[N];
int max1[N];
int main()
{
while(scanf("%d %d",&m,&n)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
memset(dp,0,sizeof(dp));
memset(max1,0,sizeof(max1));
int t;
for(int i=1;i<=m;i++) //从 分成1段 推到 分成 m段
{
t = -1000000000;
for(int j=i;j<=n;j++) //第i次记录在max1中,使用在i+1里面
{
dp[j] = max(dp[j-1],max1[j-1])+a[j];
max1[j-1]=t;
t=max(t,dp[j]);
}
}
printf("%d\n",t);
}
return 0;
}