题意:A找数
给出n个数,zjm想找出出现至少(n+1)/2次的数, 现在需要你帮忙找出这个数是多少?
输入格式:
本题包含多组数据:
每组数据包含两行。
第一行一个数字N(1<=N<=999999) ,保证N为奇数。
第二行为N个用空格隔开的整数。
数据以EOF结束。
输出格式:
对于每一组数据,你需要输出你找到的唯一的数。
样例输入:
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
样例输出:
3
5
1
思路:
一共有N个数,N为奇数,要求找出出现至少(N+1)/2次的数,我将N个数据存于vector容器中(数据量挺大,直接开数组mle),并将数据排序,由于找的这个数至少出现(N+1)/2次,所以,所以它一定出现在a[N/2]
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
int N,t;
vector<int> a;
int main(){
while(scanf("%d",&N)!=EOF){
a.clear();
for(int i=0;i<N;i++){
scanf("%d",&t);
a.push_back(t);
}
sort(a.begin(),a.end());
printf("%d\n",a[N/2]);
}
return 0;
}
题意:B三维迷宫
zjm被困在一个三维的空间中,现在要寻找最短路径逃生!
空间由立方体单位构成。
zjm每次向上下前后左右移动一个单位需要一分钟,且zjm不能对角线移动。
空间的四周封闭。zjm的目标是走到空间的出口。
是否存在逃出生天的可能性?如果存在,则需要多少时间?
输入格式:
输入第一行是一个数表示空间的数量。
每个空间的描述的第一行为L,R和C(皆不超过30)。
L表示空间的高度,R和C分别表示每层空间的行与列的大小。
随后L层,每层R行,每行C个字符。
每个字符表示空间的一个单元。’#‘表示不可通过单元,’.'表示空白单元。
zjm的起始位置在’S’,出口为’E’。每层空间后都有一个空行。
L,R和C均为0时输入结束。
输出格式:
每个空间对应一行输出。
如果可以逃生,则输出如下
Escaped in x minute(s).
x为最短脱离时间。
如果无法逃生,则输出如下
Trapped!
样例输入:
3 4 5
S…
.###.
.##…
###.#
##.##
##…
#.###
####E
1 3 3
S##
#E#
0 0 0
样例输出:
Escaped in 11 minute(s).
Trapped!
思路:
升级了一下的迷宫问题,二维–>三维,仍旧使用bfs遍历求最小路径,只不过多了一维处理。
首先将符号表示的迷宫转化为0/1式,0表示可以通过,1表示不可以通过,记录起点终点的坐标信息。在point中增加一个信息ans,记录到达该点走过的路径长度。
注意点!!!这个题的我设置的坐标顺序和我习惯上的不太一样,要格外注意一下,因为这个愿意wa了好几次,还有每次队列都要先清空!!
代码:
#include<iostream>
#include<queue>
using namespace std;
struct point{
int x,y,z,ans;
void set(int a,int b,int c,int d){x=a;y=b;z=c;ans=d;}
};
int a[30][30][30];
//int vis[30][30][30]; //记录是否到达过
queue<point> q;
int dx[]={1,-1,0,0,0,0};
int dy[]={0,0,1,-1,0,0};
int dz[]={0,0,0,0,1,-1};
int l,r,c;
int bx,by,bz,ex,ey,ez;
void bfs(int x,int y,int z)
{
while(!q.empty()) q.pop(); //先清空!!
int flag=0;
point v;
v.set(x,y,z,0);
q.push(v);
while(!q.empty())
{
point u=q.front();
q.pop();
if(u.x==ex&&u.y==ey&&u.z==ez) {
cout<<"Escaped in "<<u.ans<<" minute(s)."<<endl;
flag=1;
break;
}
for(int i=0;i<6;i++) //判断周围空格是否可走
{
if(u.x+dx[i]>=0&&u.x+dx[i]<r&&u.y+dy[i]>=0
&&u.y+dy[i]<c&&u.z+dz[i]>=0&&u.z+dz[i]<l
&&a[u.z+dz[i]][u.x+dx[i]][u.y+dy[i]]!=1) //未越界且可访问
{
point t;
int X=u.x+dx[i];int Y=u.y+dy[i];
int Z=u.z+dz[i];int A=u.ans+1;
t.set(X,Y,Z,A);
a[Z][X][Y]=1;
q.push(t);
}
}
}
if(!flag) cout<<"Trapped!"<<endl;
}
int main(){
char ch;
while(cin>>l>>r>>c){
if(l==0&&r==0&&c==0) break;
for(int i=0;i<l;i++)
for(int j=0;j<r;j++)
for(int k=0;k<c;k++){
cin>>ch;
if(ch=='S'){
bx=j;by=k;bz=i;
a[i][j][k]=0;
}
else if(ch=='E'){
ex=j;ey=k;ez=i;
a[i][j][k]=0;
}
else if(ch=='.')
a[i][j][k]=0;
else a[i][j][k]=1;
}
bfs(bx,by,bz);
}
return 0;
}
题意:C扫楼
东东每个学期都会去寝室接受扫楼的任务,并清点每个寝室的人数。
每个寝室里面有ai个人(1<=i<=n)。从第i到第j个宿舍一共有sum(i,j)=a[i]+…+a[j]个人
这让宿管阿姨非常开心,并且让东东扫楼m次,每一次数第i到第j个宿舍sum(i,j)
问题是要找到sum(i1, j1) + … + sum(im,jm)的最大值。且ix <= iy <=jx和ix <= jy <=jx的情况是不被允许的。也就是说m段都不能相交。
注:1 ≤ i ≤ n ≤ 1e6 , -32768 ≤ ai ≤ 32767 人数可以为负数。。。。(1<=n<=1000000)
输入格式:
输入m,输入n。后面跟着输入n个ai
输出格式:
输出最大和
样例输入:
1 3 1 2 3
2 6 -1 4 -2 3 -2 3
样例输出:
6
8
思路:
定义dp[i][j]为前j个数取出i段得到的最大值,那么状态转移方程为dp[i][j]=max(dp[i][j-1]+a[j],dp[i-1][k]+a[j]) , i-1<=k<=j-1,(两种情况:将a[j]并入dp[i][j-1]的最后一个子串,a[j]独自为一串)。
这个题数据量挺大,考虑节省空间支出,从转移方程可以看出,计算dp[i][j]只需要知道dp[i][j-1],以及dp[i-1][k](i-1=<k<=j)中最大值即可,所以我们可以将dp数组第一维去掉。
定义f来记录将从j个元素中取i-1段中的最大值,得到新的转移方程dp[j]=max(dp[j-1]+a[j],f[j-1]+a[j])
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=5*1e8;
const int mSize=1e6+10;
int a[mSize],dp[mSize],f[mSize];
int m,n,ans;
int main() {
while(scanf("%d%d",&m,&n)!=EOF){
memset(dp,0,sizeof(dp));
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=m;i++){
ans=-inf;
for(int j=i;j<=n;j++){
dp[j]=max(dp[j-1]+a[j],f[j-1]+a[j]);
f[j-1]=ans;
ans=ans>=dp[j]?ans:dp[j];
}
}
printf("%d\n",ans);
}
return 0;
}