程序设计思维与实践week12作业

A - 必做题 - 1 HDU - 1029

描述

给出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+1)/2则输出;

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int n;
int num[maxn];
int main(){
    
    
    while(cin>>n){
    
    
        int p=(n+1)/2;
        for(int i=0;i<n;i++)
            scanf("%d",&num[i]);
        sort(num,num+n);

        int ans=0,count=0,nownum=num[0];
        for(int i=0;i<n;i++){
    
    
            if(num[i]==nownum){
    
    
                count++;
                if(count>=p){
    
    
                    cout<<num[i]<<endl;
                    break;
                }
            }
            else{
    
    
                nownum=num[i]; count=1;
            }
        } 
    }
    return 0;
}

B - 必做题 - 2 POJ - 2251

描述

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!

想法

可以把这道题当做图遍历问题,三维的遍历;
创建三维数组mp记录迷宫每个点是否可以通过,1代表不能通过,并在输入过程中记录起点和终点。采用队列的bfs搜索进行走迷宫模拟,六个方向在常量数组dx,dy,dz中给出。注意bfs遍历过程中边界的判断以及队列元素的删除。用标记flag记录是否成功。

代码

#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
int L,R,C,step,flag;
int sx,sy,sz,ex,ey,ez;
int mp[35][35][35];
int dx[6]={
    
    0,0,0,0,1,-1};
int dy[6]={
    
    0,0,1,-1,0,0};
int dz[6]={
    
    1,-1,0,0,0,0};
struct place{
    
    //节点结构体;
    int x,y,z,step;//步长;
    place(int a,int b,int c,int d){
    
    
       x=a,y=b,z=c,step=d;
    }
};

queue<place> q;
int vis[35][35][35];

void init(){
    
    
    step=0,flag=0;
    memset(mp,0,sizeof(mp));
    memset(vis,0,sizeof(vis));
    while(!q.empty())q.pop();
}

int main()
{
    
    
  while (1){
    
    
      init();
      cin>>L;cin>>R;cin>>C;
      if(L==0&&R==0&&C==0)break;
      char c;
      for(int i=0;i<L;i++){
    
    
        for(int j=0;j<R;j++)
            for(int k=0;k<C;k++){
    
    
                cin>>c;
				if(c == '#') mp[i][j][k]=1;
                if(c == 'S') sx=i,sy=j,sz=k;
                if(c == 'E') ex=i,ey=j,ez=k;
            }
      }
      
      q.push(place(sx,sy,sz,0));
      vis[sx][sy][sz]=1;
      while(!q.empty()){
    
    
         place nowp=q.front();
         q.pop();//不丢;
         for(int i=0; i<6; i++){
    
    
             int nx=nowp.x+dx[i];
             int ny=nowp.y+dy[i];
             int nz=nowp.z+dz[i];
             if( mp[nx][ny][nz]!=1 && vis[nx][ny][nz]==0 
                &&nx>=0 &&nx<L &&ny>=0 &&ny<R &&nz>=0 &&nz<C){
    
    
                   q.push(place(nx,ny,nz,nowp.step+1));
                   vis[nx][ny][nz]=1;
                }
         }
         if(vis[ex][ey][ez]==1){
    
    
             flag=1;step=nowp.step+1;break;
         }
      }
      if(flag==1)printf("Escaped in %d minute(s).\n",step);
      else printf("Trapped!\n");
  }
  return 0;
}

C - 必做题 - 3 HDU - 1024

描述东东每个学期都会去寝室接受扫楼的任务,并清点每个寝室的人数。

每个寝室里面有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 处理到 EOF

输出

输出最大和

样例

输入:

1 3 1 2 3
2 6 -1 4 -2 3 -2 3

输出:

6
8 

Hint:数据量很大,需要scanf读入和dp处理。

想法

动态规划问题,定义dp[i][j]为前j个宿舍取i组获得的最大值,第j个宿舍必须包含在其中;状态转移方程较难:
dp[i][j]=max{dp[i][j−1],max(dp[i−1][k],1≤k≤j−1)}+A[j]
1,即考虑加入宿舍j,第一种情况是j加入最后一组,dp[i][j-1]直接加上A[j]。
2,第二种情况是j自己成为一组,加上前边的j-1个宿舍(可以不包含j-1)分成,i-1组的最大值。
由于数据范围太大,我们考虑降到一维。对于这个最大值,我们用p[]保存,dp[i]表示取到第i个房间的最大值;

for(int i=1;i<=m;i++){
    
    //层数 
			ans=-maxn1;
			for(int k=i;k<=n;k++){
    
    //最右边界; 
				dp[k]=max(dp[k-1]+a[k],p[k-1]+a[k]);
				p[k-1]=ans;
				ans=max(ans,dp[k]);//保证是当前层最大值; 
			}
		} 

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn1=1e9;
const int maxn2=1e6+10;
int a[maxn2];
int dp[maxn2],p[maxn2];
int m,n,ans;

int main()
{
    
    
	while(scanf("%d%d",&m,&n)!=EOF){
    
    
		ans=0;
		memset(dp,0,sizeof(dp));
		memset(p,0,sizeof(p));
		for(int i=1;i<=n;i++)scanf("%d",&a[i]);
		
		for(int i=1;i<=m;i++){
    
    //层数 
			ans=-maxn1;
			for(int k=i;k<=n;k++){
    
    //最右边界; 
				dp[k]=max(dp[k-1]+a[k],p[k-1]+a[k]);
				p[k-1]=ans;
				ans=max(ans,dp[k]);//保证是当前层最大值; 
			}
		} 
		printf("%d\n",ans);	
	}
	return 0;
 } 

Guess you like

Origin blog.csdn.net/weixin_44080131/article/details/106312834