河南省第十一届ACM/ICPC大学生程序设计竞赛题解

河南省第十一届省赛
感觉这一套题挺好的,很多算法都涉及到了。只是ac的多的题我写不好。。。

A 计划日

写的时候想复杂了,只需年月日的日+需要加的天数,然后处理就好了,不用分别处理月和年了。

#include <stdio.h>
int a[13]={0,31,0,31,30,31,30,31,31,30,31,30,31};
void ra(int yy){
    if(yy%400==0||(yy%100!=0&&yy%4==0))a[2]=29;
    else a[2]=28;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        int s,w,n;
        scanf("%d%d%d",&s,&w,&n);
        int yy,mm,dd;
        yy=s/10000;
        mm=s/100%100;
        dd=s%100;
        ra(yy);
        int week = (w+n)%7;
        if(week==0)week=7;
         
        while(n--){
            dd++;
            if(dd>a[mm]){
                dd=1;
                mm++;
            }
            if(mm==13){
                mm=1;
                yy++;
                ra(yy);
            }
        }
        printf("%d%02d%02d %d\n",yy,mm,dd,week);
         
    }
    return 0;
}

B 治安管理

队友cyj大佬写的,看着是模拟题–

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N=100005;
const int inf=0x3f3f3f3f;
typedef long long ll;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m,s,f,x;
        int a[100001]={0};
        scanf("%d%d%d%d",&n,&m,&s,&f);
        for(int i=0;i<n;i++){
            scanf("%d",&x);
            a[x]++;
        }
        for(int i=0;i<n;i++){
            scanf("%d",&x);
            a[x]--;
        }
        int min,max;
        if(s==0){
            min=a[0];
            max=a[0];
        }else{
            min=n+1;
            max=0;
        }
        for(int i=1;i<f;i++){
            a[i]+=a[i-1];
            if(i>=s){
                if(a[i]>max)max=a[i];
                if(a[i]<min)min=a[i];
            }
        }
        if(min>=m){
            printf("YES %d\n",max);
        }else{
            printf("NO %d\n",min);
        }
    }
    return 0;
}
 

C 山区修路

dp还是不会。。。
暴力dp,第一座山处理之后,后面的山费用由前一座山的高度推出,求两座山的自身高度到最高高度时需要填补的费用和补坡的费用。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N=100005;
const int inf=0x3f3f3f3f;
typedef long long ll;
int T,n,m,ans;
int a[N],dp[N][105];
int main()
{
    int T,x,i,h1,h2;
    scanf("%d",&T);
    while(T--){
        memset(dp,inf,sizeof(dp));
        scanf("%d %d",&n,&x);
        int mx=0;
        for(i=1;i<=n;i++){
            scanf("%d",&a[i]);
            if(a[i]>mx) mx=a[i];
        }
        for(i=a[1];i<=mx;i++){		//初始化第一个山,求它到最高高度分别需要多少费用
            dp[1][i]=(i-a[1])*(i-a[1]);
        }
        for(i=2;i<=n;i++)			//列举2~n山
            for(h1=a[i-1];h1<=mx;h1++)//i-1山的高度
                for(h2=a[i];h2<=mx;h2++){//i山的高度
                    dp[i][h2]=min(dp[i][h2],dp[i-1][h1]+(h2-a[i])*(h2-a[i])+(int)abs(h2-h1)*x);
                    //第i山的h2高度的费用,由前一座山h1高度的费用+i山补的高度费用+两座山坡的费用推出
                }
        ans=inf;
        for(i=a[n];i<=mx;i++)
            ans=min(ans,dp[n][i]);
        printf("%d\n",ans);
    }
    return 0;
}

D 求XF+闭包(待补)

E 物流配送

可能我对模板题有点误解。。。我太菜了看了一会才看出来是最小费用流,而且知道后并不清楚怎么改。。。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=5e4+10;
const int inf=0x3f3f3f3f;
typedef long long ll;
int T,n,m,ans,st,en;
struct node{
    int to,next,flow,dis;
}s[N];
int head[N],num=1,maxflow,mincost;
int a[N],b[N];
int dis[N],minf[N],pre[N];
void add(int u,int v,int w,int cap){
    s[++num]=(node){v,head[u],w,cap}; 
    head[u]=num;
}
int spfa(){
    memset(dis,inf,sizeof(dis));
    int vis[N]={0};
    vis[st]=1;
    minf[st]=1<<30;
    dis[st]=0;
    queue<int>q; q.push(st);
    while(!q.empty()){ 
        int u=q.front(); q.pop();
        vis[u]=0;
        for(int i=head[u];i;i=s[i].next){
            if(!s[i].flow) continue;
            int v=s[i].to;
            if(dis[v]>dis[u]+s[i].dis){
                dis[v]=dis[u]+s[i].dis;
                minf[v]=min(minf[u],s[i].flow);
                pre[v]=i;
                if(!vis[v]){
                    vis[v]=1;q.push(v);
                }
            }
        }
    }
    return dis[en]!=inf;
}
void MCMF(){
    while(spfa()){
        int cur=en;
        maxflow+=minf[en];
        mincost+=minf[en]*dis[en];
        while(cur!=st){
            int fa=pre[cur];
            s[fa].flow-=minf[en];
            s[fa^1].flow+=minf[en];
            cur=s[fa^1].to;
        }
    }
}
int main()
{
    int i,j,k,x,y,z;
    cin>>n;
    st=0;en=n+1;    
    for(i=1;i<=n;i++) {
        scanf("%d",&x);
        add(0,i,x,0);//起点到各个点的流量
        add(i,0,0,0);
    }
    for(i=1;i<=n;i++) {
        scanf("%d",&x);
        add(i,n+1,x,0);//各个点到终点的流量
        add(n+1,i,0,0);
    }
     
    for(i=1;i<n;i++){
        cin>>x>>y>>k;
        add(x,y,inf,k);//给出的边流量无限,无向图的费用正反都一样
        add(y,x,inf,k);
    }
    MCMF();//剩下的模板不用改
    cout<<mincost;
    return 0;
}
 

F Gene mutation

开始题没读懂并不知道怎么搞。。。
要翻转是长串,题目要求子串的递增差值是否和长串任意一段是否匹配,长串取出子串长度然后排序比较。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
using namespace std;
const int N=20005;
const int inf=0x3f3f3f3f;
int x[N],y[N],a[N];
int main()
{
    int T,n,i,j,m,k,c;
    scanf("%d",&T);
    while(T--){
        int ans=0;
        scanf("%d",&n);
        for(i=1;i<=n;i++) 
            scanf("%d",&x[i]);
        scanf("%d",&c);
        for(i=1;i<=c;i++)
            scanf("%d",&y[i]);
        sort(y+1,y+1+c);
        for(i=1;i<c;i++)
            y[i]=y[i+1]-y[i];
        for(i=1;i<=n-c+1;i++){
            for(j=i;j<i+c;j++){
                a[j-i+1]=x[j];
                 
            }
            sort(a+1,a+1+c);
            int f=0;
            for(j=1;j<c;j++){
            //  printf("%d ",a[j+1]-a[j]);
                if(a[j+1]-a[j]!=y[j]){
                    f=1;break;
                }
            }
            if(!f) ans++;
        //  printf("\n");
        }
        printf("%d\n",ans);
    }
 
    return 0;
}
 

G Checkpoints

感觉这题比上一题简单多了,这才是bfs裸题,但是写出来的人比上一题少好多。
两点之间的最短路,bfs无疑了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int N=105;
const int inf=0x3f3f3f3f;
typedef long long ll;
int T,n,m,ans,a,b;
vector<int>v[N];
int vis[N];
struct node{
    int x,cnt;
}s,t;
void bfs(){
    queue<node>q;
    s.x=a; s.cnt=0;
    vis[a]=1;
    q.push(s);
    while(!q.empty()){
        t=q.front(); q.pop();
        //printf("%d ",t.x);
        if(t.x==b) {
            printf("%d",t.cnt); return ;
        }
        s.cnt=t.cnt+1;
        for(int i=0;i<v[t.x].size();i++){        
            int to=v[t.x][i];
            if(vis[to]==0){
                vis[to]=1;
                s.x=to;
                q.push(s);
            }
        }
    }
}
int main()
{
    int i,j,k,x,y;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d %d %d",&n,&m,&a,&b);
        while(m--){
            scanf("%d %d",&x,&y);
            v[x].push_back(y);
            v[y].push_back(x);
        }
        bfs();
    }
    return 0;
}

H Attack City and Capture Territory

尼姆博弈模板,异或和为0时先手输,否则先手赢。
很好理解,异或和为0时,有n堆物品,n%2==0,并且一定能找到两个数量一样多的堆。先手拿一堆中的任意数量物品时,后手在对应堆也拿相同数量的物品,后手是最后拿物品的人,此时后手必赢

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N=100005;
const int inf=0x3f3f3f3f;
typedef long long ll;
int T,n,m,ans;
int a[N],dp[N][105];
int main()
{
    int T,x,i,h1,h2;
    scanf("%d",&T);
    while(T--){
        ans=0;
        scanf("%d",&n);
        while(n--){
            scanf("%d",&x);
            ans^=x;
        }
        if(ans==0) puts("Liu_B is not sure to win.");
        else puts("Liu_B is sure to win.");
    }
    return 0;
}

I Image Recognition(待补)

J Jigsaw Puzzle(待补)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ACM-ICPC(国际大学生程序设计竞赛)是一项全球性的大学生程序设计比赛,每年吸引来自世界各地的顶尖大学代表队参与。ACM-ICPC竞赛的核心内容是团队编程和问题决能力。 首先,ACM-ICPC竞赛对参赛选手的编程能力要求很高。参赛队伍需要在规定的时间内决一系列的算法问题,这些问题常常包含复杂的数据结构和算法,要求选手在有限的时间内设计和实现高效的程序。 其次,ACM-ICPC竞赛强调团队协作。每个队伍由三名选手组成,他们需要分工合作,保持良好的沟通与协调,共同决问题。团队成员需要相互理、相互信任,快速地协商和决策,同时要保持高效的任务分配和时间管理。 此外,ACM-ICPC竞赛也需要选手具备良好的问题决能力。这些问题往往是实际应用或理论推导相关的,选手需要从数学、计算机科学和算法等多个角度出发,找到最佳决方案。在面对问题时,选手需要对问题进行分析、抽象和建模,运用各种算法和数据结构进行决。 对于参赛选手来说,ACM-ICPC提供了一个学习与交流的平台。在比赛中,选手可以接触到不同国家和地区的优秀程序设计人才,学习他们的思维方式和编程技巧。同时,ACM-ICPC还举办了一系列的培训和研讨会,让选手有机会深入了计算机科学和算法领域最新的研究成果。 总之,ACM-ICPC国际大学生程序设计竞赛是一个挑战性与学习性兼具的比赛。它要求选手具备扎实的编程技能、团队合作能力和问题决能力。参与此竞赛不仅可以锻炼自己的编程能力,还能与全球的顶尖程序设计人才进行交流,拓宽自己的视野和思维方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值