scau数据结构习题

18708 最大子段和
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0

题型: 编程题 语言: 不限定

Description
一个整数序列,选出其中连续且非空的一段使得这段和最大。

输入格式
第一行是一个正整数N,表示了序列的长度(0=<N<=200000)。
第二行包含N个绝对值不大于10000的整数ai。
输出格式
一个整数,为最大的子段和。子段的最小长度为1。数据确保结果在类型int范围内。
输入样例
7
2 -4 3 -1 2 -4 3
输出样例
4
提示
【样例说明】

2,-4,3,-1,2,-4,3中,最大的子段和为4,该子段为第三元素至第五元素,即3,-1,2。

题解:典型的动态规划或者分治。
分治法(难)

#include<iostream>
#include<cstdio>
using namespace std;
int num[200010];
int f(int left,int right)
{
   
    //printf("%d %d\n",left,right);
    if(right==left+1)
    {
   
        return max(num[left],max(num[right],num[left]+num[right]));
    }
    else if(left==right)
    {
   
        return num[left];
    }
    //过中点
    int mid=(left+right)/2;
    int mmax=num[mid],temp=num[mid];
    //从中点向左延伸,寻找连续子序列最大值
    for(int i=mid-1;i>=left;i--)
    {
   
        temp+=num[i];
        mmax=max(mmax,temp);
    }
    temp=mmax;
    for(int i=mid+1;i<=right;i++)
    {
   
        temp+=num[i];
        mmax=max(mmax,temp);
    }
    int mmax1=f(left,mid-1);//注意是mid-1即不过中点
    int mmax2=f(mid+1,right);
    //printf("%d %d %d\n",mmax1,mmax2,mmax);
    //printf("*%d %d\n",left,right);
    return max(max(mmax1,mmax2),mmax);
}
int main ()
{
   
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
   
        scanf("%d",&num[i]);
    }
    long long mmax=f(1,n);
    cout<<mmax<<endl;
    return 0;
}

动态规划法

#include<iostream>
#include<cstdio>
using namespace std;
long long dp[200010];
int num[200010];
int main ()
{
   
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
   
        scanf("%d",&num[i]);
    }
    long long mmax=-20000;
    for(int i=1;i<=n;i++)
    {
   
        if(dp[i-1]>0)
        {
   
            dp[i]=num[i]+dp[i-1];
        }
        else dp[i]=num[i];
        if(dp[i]>mmax)
        {
   
            mmax=dp[i];
        }
    }
    cout<<mmax<<endl;
    return 0;
}

18709 魔法
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: 不限定

Description
农夫约翰的奶牛场有很多奶牛,奶牛有黑白两种颜色。现在奶牛们排成整齐的一列去参加镇上的游行活动。
约翰希望白色奶牛都排在前面,黑色的奶牛都排在后面。但现在队列中奶牛的颜色是混乱的,并且奶牛们都不愿意改变位置。
幸运的是,约翰有一根魔法棒,每挥舞一次魔法棒就可以改变一头奶牛的颜色。
请问,约翰至少要挥舞多少次魔法棒,才能将队列改成他希望的状态。注意,可以将所有的奶牛都变成白色,或者都变成黑色。

输入格式
第一行一个正整数n,表示奶牛的头数。(1<=n<=200000)。
第二行n个正整数,均为1或2,1表示白色奶牛,2表示黑色奶牛。
输出格式
一个正整数,表示挥舞魔法棒的最少次数。
输入样例
7
2 2 1 1 1 2 1
输出样例
3
提示
可以把1和2号奶牛变成1,7号奶牛变成2,或者全部奶牛变成1,最少需要3次。

题解:我们可以o(n)枚举白牛与黑牛的交界处,这N种情况的最值就是答案啦。那枚举完,假设第一头黑牛的位置是pos,我们用sum黑表示黑牛前n项和,sum白表示白牛。那么就有变化次数就是=sum黑[pos-1]+sum白[n]-sum[pos-1]。

#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
int sum[200010][2];//0表示白,1表示黑
int main ()
{
   
    int n;
    scanf("%d",&n);
    int num;
    for(int i=1;i<=n;i++)
    {
   
        scanf("%d",&num);
        sum[i][0]=sum[i-1][0];
        sum[i][1]=sum[i-1][1];
        if(num==1)
        {
   
            sum[i][0]=sum[i-1][0]+1;
        }
        else
        {
   
            sum[i][1]=sum[i-1][1]+1;
        }
    }
    int mmax=1000000;
    for(int i=1;i<=n;i++)
    {
   
        int temp1=sum[i][1]-sum[i][0]+sum[n][0];
        mmax=min(temp1,mmax);
    }
    printf("%d\n",mmax);
    return 0;
}

18711 字符串去重
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: 不限定

Description
一个完全由小写字母组成的长度为n的字符串,现在要求你去除所有重复的字母,并将剩下的字母按从小到大的次序输出。
如输入baaadccaab,输出abcd。

输入格式
第一行一个整数n,表示字符串长度(0<=n<=100000)。
第二行一个字符串。
输出格式
去除所有重复的字母,并将剩下的字母按从小到大的次序输出。
输入样例
10
baaadccaab
输出样例
abcd

题解:直接对出现的字符进行标记就可以了

#include<iostream>
#include<cmath>
#include<cstdio>
#include<set>
#include<string>
#include<cstring>
using namespace std;
char s[100010];
int book[27];
int main ()
{
   
    int n;
    scanf("%d",&n);
    getchar();
    gets(s);
    for(int i=0;i<n;i++)
    {
   
        book[s[i]-96]=1;
    }
    for(int i=1;i<=26;i++)
    {
   
        if(book[i])
        printf("%c",96+i);
    }
    return 0;
}

18710 统计不同数字的个数(升级版)
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: 不限定

Description
由键盘输入n个整数,统计不同数字的个数(0<=n<=200000)。

PS:此题目和1040仅数据规模不同。但如果使用如下O(n2)级别的算法必然会超时。
int main()
{
int a[21],i,c=0,b,j;
for(i=1;i<=20;i++)
{
cin>>b;
for(j=1;j<=c;j++)
{
if(b==a[j])
{
break;
}
}
if(j>c)
{
a[c+1]=b;
c++;
}
}
cout<<c;
return 0;
}

输入格式
第一行一个整数n(0<=n<=200000)。
第二行n个整数a1,a2…an,(0<=ai<=200000)。
输出格式
仅一行,不同数字的个数。
输入样例
70 5 14 22 19 2 99 67 13 66 5 93 44 38 22 11 39 22 33 11
输出样例
16

题解:因为整数范围很小,直接开一个200000的数组对出现的数字标记

#include<iostream>
#include<cmath>
#include<cstdio>
#include<set>
#include<string>
#include<cstring>
using namespace std;
int book[200010];
int main ()
{
   
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
   
        int num;
        scanf("%d",&num);
        book[num]=1;
    }
    int ans=0;
    for(int i=0;i<=200000;i++)
    {
   
        if(book[i])
        {
   
            ans++;
        }
    }
    cout<<ans<<endl;
    return 0;
}

18063 圈中的游戏
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0

题型: 编程题 语言: G++;GCC;VC
Description
有n个人围成一圈,从第1个人开始报数1、2、3,每报到3的人退出圈子。编程使用链表找出最后留下的人。

输入格式
输入一个数n,1000000>=n>0
输出格式
输出最后留下的人的编号
输入样例
3
输出样例
2

题解:直接数组来模拟

#include<iostream>
#include<cmath>
#include<cstdio>
#include<set>
#include<string>
#include<cstring>
using namespace std;
int book[200010];
int main ()
{
   
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
   
        int num;
        scanf("%d",&num);
        book[num]=1;
    }
    int ans=0;
    for(int i=0;i<=200000;i++)
    {
   
        if(book[i])
        {
   
            ans++;
        }
    }
    cout<<ans<<endl;
    return 0;
}

18712 组合问题
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: 不限定

Description
找出从自然数1、2、……、m中任取k个数的所有组合,组合中字典序大的先输出。
例如m=5,k=3,应输出
5 4 3
5 4 2
5 4 1
5 3 2
5 3 1
5 2 1
4 3 2
4 2 1
3 2 1

输入格式
两个整数m和k,(1<=k<=m<=10)
输出格式
按字典序输出所有组合
输入样例
5 2
输出样例
5 4
5 3
5 2
5 1
4 3
4 2
4 1
3 2
3 1
2 1

题解:dfs进入一次回溯时,前面已经出现的数字标记,然后按顺序找到没标记的数字就可以了

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<stack>
using namespace std;
int book[12];
int box[12];
int n,k;
void dfs(int step)
{
   
    if(step==k+1)
    {
   
        for(int i=1;i<=k;i++)
        {
   
            printf("%d ",box[i]);
        }
        printf("\n");
        return;
    }
    for(int i=n;i>=1;i--)
    {
   
        if(!book[i]&&i<box[step-1])
        {
   
            box[step]=i;
            book[i]=1;
            dfs(step+1);
            book[i]=0;
        }
    }
    return;
}
int main ()
{
   
    scanf("%d%d",&n,&k);
    box[0]=n+1;
    dfs(1);
    return 0;
}

18713 整数的分解
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: 不限定

Description
输出一个正整数n的分解形式。例如,当n=4时,输出:
4=4
4=3+1
4=2+2
4=2+1+1
4=1+1+1+1
共计 5 种形式。
当n=7时,共有15种形式。
当n=10时,共有42种形式。

输入格式
一个整数n(1<=n<=10)。
输出格式
n的全部分解形式,注意分解式中数字值大的排在前面,如第一个数字值相同,那么比较第二个数字。
输入样例
4
输出样例
4=4
4=3+1
4=2+2
4=2+1+1
4=1+1+1+1

题解:很明显又是一次dfs的题,把每个等式的第一个式子枚举出来,很明显dfs里面放一个for对吧,就好比数字4,那他有4个等式,每个等式第一个数字分别是4,3,2,1,比如我们拿第二个等式,枚举完3后,那4-3剩下的部分就继续dfs,让他继续分解,不过要注意后面的分解出来的数比前面的要小。

#include<iostream>
#include<cstdio>
using namespace std;
int book[12];
int num;
void dfs(int n,int pri)//pri表示前面的数值
{
   
    if(n<=0)
    {
   
        printf("%d",num);
        int pos=1;
        for(int i=num;i>=0;i--)
        {
   
            for(int j=1;j<=book[i];j++)
            {
   
                if(pos)
                {
   
                    printf("=");
                    pos=0;
                }
                else printf("+");
                printf("%d",i);
            }
        }
        printf("\n");
        return;
    }
    for(int i=n;i>=1;i--)
    {
   
        if(i>pri)
        {
   
         continue;
        }
        book[i]++;
        dfs(n-i,i);
        book[i]--;
    }
    return;
}
int main ()
{
   
    scanf("%d",&num);
    dfs(num,12);
    return 0;
} 

18714 迷宫问题
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: 不限定

Description
迷宫是一个n*m的矩阵,玩家需要迷宫入口(坐标1,1)出发,寻找路径走到出口(n,m)。
请判断玩家能否从迷宫中走出。

输入格式
第一行两个整数n和m,代表n行m列。(1<=n,m<=10)
下面n行每行m个字符,0代表可以通行,1代表不可以通行。

输出格式
如果能从迷宫走出,输出yes,否则输出no。
输入样例
8 8
00100010
00100010
00001100
01110000
00010000
01000100
01110110
00001000
输出样例
yes
提示
样例数据即为图片迷宫

题解:直接dfs或者bfs模板

#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
char mmap1[20][20];
int mmap[20][20];
int book[20][20];
int next1[4][2]={
   {
   1,0},{
   0,1},{
   -1,0},{
   0,-1} };
int main ()
{
   
    queue<pair<int,int> > que;
    int n,m;
    scanf("%d%d",&n,&m);
    getchar();
    for(int i=0;i<n;i++)
    {
   
        gets(mmap1[i]);
    }
    for(int i=0;i<n;i++)
    {
   
        for(int j=0;j<m;j++)
        {
   
            mmap[
  • 9
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值