比赛13 总结

来源:互联网 发布:古埃及人知乎 编辑:程序博客网 时间:2024/06/11 22:50

  • T1
    • 题面
    • 题意
    • 代码
  • T2
    • 题面
    • 题意
    • 方法
    • 代码
  • T3
    • 题面
    • 题意
    • 方法
    • 代码
  • T4
    • 题面
    • 题意
    • 方法
    • 代码
  • T5
    • 题面
    • 题意
    • 方法
    • 代码

T1

题面

题意

输入n,下面四行每行四个数,若某一行前两个数和后两个数的最小值之和小于等于n,输出前一个最小值和n-那个值

代码

#include<bits/stdc++.h>using namespace std;int n,k,l,a[5][5],b[5],c[5];int main(){    int i,j;    cin>>n;    for(i=1;i<=4;i++)    {        for(j=1;j<=4;j++)        {            cin>>a[i][j];        }    }    for(i=1;i<=4;i++)    {        b[i]=min(a[i][1],a[i][2]);        c[i]=min(a[i][3],a[i][4]);    }    for(i=1;i<=4;i++)    {        if(b[i]+c[i]<=n)        {            cout<<i<<" "<<b[i]<<" "<<n-b[i];            return 0;        }    }    cout<<-1;}

T2

题面

题意

输入n,k和n个数,求该序列和最小的子序列.每个子序列以1-k间的一个数为头,第二个数的下标加k直到n.
输出最小子序列的头

方法

暴力枚举

代码

#include<bits/stdc++.h>#define ll long longusing namespace std;ll n,k,a[100005],ans,mn=10000000000,sum[100005];int main(){    ll i,j;    cin>>n>>k;    for(i=1;i<=n;i++)    {        scanf("%lld",&a[i]);//      sum[i%k]+=a[i];    }    for(i=1;i<=k;i++)    {        for(j=i;j<=n;j+=k)        {            sum[i]+=a[j];        }    }    /*    for(i=1;i<=k;i++)    {        cout<<sum[i]<<endl;    }    */    for(i=1;i<=k;i++)    {        if(mn>sum[i])        {            mn=sum[i];            ans=i;        }    }    cout<<ans;}

T3

题面

题意

输入n,k和两组数每组均有n个数,要求从第一组中选取几个数,使这几个数之和与另一组这几个位置的数之和的比值为k.输出第一组的最大和.

方法

暴力加剪枝,首先枚举并记录下当前第一组数的和对答案的影响(数组不必太大),其中对答案影响过大的数据不用记录,再加上一个布尔数组来判断是否重复,最后输出符合条件的最大数

代码

#include<bits/stdc++.h>#define N 105#define M 5000005using namespace std;short n,k,tas[N],hot,ch,ans[M],cz[M],mx;int aa;bool P[10001][20001];int main(){    int i,j,b,an,cc;    cin>>n>>k;    for(i=1;i<=n;i++)    {        cin>>tas[i];    }    aa=1;    ans[1]=cz[1]=0;    for(i=1;i<=n;i++)    {        cin>>hot;        ch=tas[i]-hot*k;        b=aa;        for(j=1;j<=b;j++)        {            an=tas[i]+ans[j];            cc=ch+cz[j];            if(cc>=(i-n)*100)//剪枝,减小复杂度            if(!P[an][cc])            {                aa++;                ans[aa]=an;                cz[aa]=cc;                P[an][cc]=true;            }        }    }    for(i=1;i<=aa;i++)    {        if(cz[i]==0)        {            mx=max(mx,ans[i]);        }    }    if(mx==0) cout<<-1;    else cout<<mx;    return 0;}

T4

题面

题意

输入点数n,边数m,和m条边,包括两端和最小最大的可通过值,输出最长的一段可通过范围的长度.

方法

首先将边按照最大可通过值排序,然后依次为已选边,通过并查集来判断1和n是否有同一个父亲,再算出最大可通过值与最小可通过值的差加1.

代码

#include<bits/stdc++.h>#define N 1005#define M 3005using namespace std;int m,n,fa[N],ans;struct Bn{    int from,to,mn,mx;}bn[M];bool cmp(Bn u,Bn v){    if(u.mx==v.mx) return u.mn<v.mn;    return u.mx>v.mx;}int getfa(int u)//并查集{    if(fa[u]==u) return u;    else return fa[u]=getfa(fa[u]);}int main(){    int i,j;    cin>>n>>m;    for(i=1;i<=m;i++)    {        scanf("%d%d%d%d",&bn[i].from,&bn[i].to,&bn[i].mn,&bn[i].mx);    }    sort(bn+1,bn+m+1,cmp);    for(i=1;i<=m;i++)    {        for(j=1;j<=n;j++)        {            fa[j]=j;        }        for(j=1;j<=m;j++)        {            if(bn[j].mn<=bn[i].mn&&bn[j].mx>=bn[i].mn)            //选出的边需要与第一条选择的边有公共区域            {                fa[getfa(bn[j].from)]=getfa(bn[j].to);                if(getfa(1)==getfa(n))                {                    ans=max(ans,bn[j].mx-bn[i].mn+1);                    break;                }            }        }    }    if(ans!=0)    cout<<ans;    else    cout<<"Nice work, Dima!";}

T5

题面

题意

输入长宽m,n以及数字数k,数字串长度l,再输入数字矩阵和字符串,判断数字串中相邻两数的最大曼哈顿距离(|x1-x2|+|y1-y2|).

方法

由曼哈顿距离可得,有以下四种情况
x1-x2+y1-y2=(x1+y1)-(x2+y2).
x1-x2-y1+y2=(x1-y1)-(x2-y2).
-x1+x2+y1-y2=-(x1-y1)+(x2-y2).
-x1+x2-y1-y2=-(x1+x2)+(x2+y2).
因此要分别求出横纵坐标和与差的最值以进行比较

代码

#include<bits/stdc++.h>#define N 2005using namespace std;int m,n,k,len,hmx[10],cmx[10],hmn[10],cmn[10],s,ans,last,jl1,jl2,jl3,jl4;bool jl[10][10];int MAX(int a,int b,int c,int d){    return max(max(a,b),max(c,d));}int main(){    ios_base::sync_with_stdio(0);    int i,j;    cin>>m>>n>>k>>len;    for(i=1;i<=10;i++)    {        hmn[i]=cmn[i]=2005;    }    for(i=1;i<=m;i++)    {        for(j=1;j<=n;j++)        {            cin>>s;            hmn[s]=min(hmn[s],i+j);            hmx[s]=max(hmx[s],i+j);            cmn[s]=min(cmn[s],j-i);            cmx[s]=max(cmx[s],j-i);        }    }    cin>>last;    for(i=2;i<=len;i++)    {        cin>>s;        if(jl[s][last]==false)        {            jl1=hmx[s]-hmn[last];            jl2=cmx[s]-cmn[last];            jl3=cmx[last]-cmn[s];            jl4=hmx[last]-hmn[s];            ans=max(ans,MAX(jl1, jl2, jl3, jl4));            jl[s][last]=jl[last][s]=true;        }        last=s;    }    cout<<ans;}
原创粉丝点击