河南省11届ACM省赛--练习向:A(模拟)B(思维)C(DP)D(读题)E(费用流)F(暴力读题)G(最短路)H(博弈)

又快要到省赛了,补一补去年的题的,话说当时还没补过...

断断续续,两天写了8道,剩下两道应该是防AK的,去年榜首也是8道*2.剩下两道随缘补吧。

补题OJ:ZZULI

A-计划日(模拟)

题目链接:http://acm.zzuli.edu.cn/problem.php?id=2304

题目大意:略。

思路:照着模拟就行了。注意输出的时候02不是2

ACCode:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
   
#include<stdio.h>
#include<string.h> 
#include<math.h> 
    
#include<map>  
#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
   
#define ll long long 
#define Pair pair<int,ll>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);
 
int mon29[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};
int mon28[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
 
int main(){
    int T;scanf("%d",&T);
    while(T--){
        char s[10],ch=getchar();int day,n;
        scanf("%s%d%d",&s,&day,&n);
        int yy=0,mm=0,dd=0;
        for(int i=0;i<4;++i) yy=yy*10+s[i]-'0';
        for(int i=4;i<=5;++i) mm=mm*10+s[i]-'0';
        for(int i=6;i<=7;++i) dd=dd*10+s[i]-'0';
        for(int i=1;i<=n;++i){
            day=(day%7)+1;
            dd++;
            if(yy%4==0){
                if(dd>mon29[mm]){
                    dd=1;mm++;
                }
                if(mm>12){
                    mm=1;yy++;
                }
            }
            else{
                if(dd>mon28[mm]){
                    dd=1;mm++;
                }
                if(mm>12){
                    mm=1;yy++;
                }
            }
        }printf("%04d%02d%02d %d\n",yy,mm,dd,day);
    }
}
 
/*
 
*/

B-治安管理(思维)

题目链接:http://acm.zzuli.edu.cn/problem.php?id=2305

题目大意:略。

思路:之前CF写过一道类似的。碰到起点+1,终点-1,就行了。(去年打的时候什么都不会,胡乱暴力竟然过了??)

ACCode:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
   
#include<stdio.h>
#include<string.h> 
#include<math.h> 
    
#include<map>  
#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
   
#define ll long long 
#define Pair pair<int,ll>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);
 
int Vis[MAXN];
 
int main(){
    int T;scanf("%d",&T);
    while(T--){
        clean(Vis,0);
        int n,m,a,b;scanf("%d%d%d%d",&n,&m,&a,&b);
        for(int i=1;i<=n;++i){
            int x;scanf("%d",&x);
            Vis[x]++;
        }
        for(int i=1;i<=n;++i){
            int x;scanf("%d",&x);
            Vis[x]--;
        }int flag=1,num=0,maxx=0,minn=INF32;
//      for(int i=a;i<=b;++i) cout<<i<<" : "<<Vis[i]<<endl;
        for(int i=0;i<a;++i) num+=Vis[i];
        for(int i=a;i<b;++i){
            num+=Vis[i];
            maxx=max(maxx,num);
            minn=min(minn,num);
//          cout<<num<<" "<<maxx<<" "<<minn<<endl;
            if(num<m){
                flag=0;
            }
        }
        if(flag==0) printf("NO %d\n",minn);
        else printf("YES %d\n",maxx);
    }
}
 
/*
 
*/

C-山区修路(DP)

题目链接:http://acm.zzuli.edu.cn/problem.php?id=2306

题目大意:略

思路:这一看就是DP 啊,没毛病,但是状态转移方程是什么?一开始是想枚举所有的n*100*100的情况,但1e9的复杂度很让我害怕,后来实在找不到好的方法,就试着交了发,没想到竟然过了??(但是我深知代码丑陋,因此若有大佬路过,请务必留言告诉我更快的方法/谢过)

ACCode:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
   
#include<stdio.h>
#include<string.h> 
#include<math.h> 
    
#include<map>  
#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
   
#define ll long long 
#define Pair pair<int,ll>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=1e3+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);
 
int dp[MAXN][110],a[MAXN];
int n,x;
 
int main(){
    std::ios::sync_with_stdio(false);
    int T;cin>>T;
    while(T--){
        cin>>n>>x;clean(dp,INF32);
        for(int i=1;i<=n;++i) cin>>a[i];
        for(int i=a[1];i<=100;++i) dp[1][i]=(i-a[1])*(i-a[1]);
        for(int i=2;i<=n;++i){
            for(int j=a[i];j<=100;++j){
                for(int k=a[i-1];k<=100;++k){
                    dp[i][j]=min(dp[i][j],dp[i-1][k]+((j-a[i])*(j-a[i]))+abs(j-k)*x);
                }
            }
        }int ans=INF32;
        for(int i=0;i<=100;++i) ans=min(ans,dp[n][i]);
        cout<<ans<<endl;
    }
}
 
/*
 
*/

D-求XF+闭包(读题+暴力)

题目链接:http://acm.zzuli.edu.cn/problem.php?id=2307

题目大意:就是给你一个全集U,一个集合A,给你一些关系F,让你从A和F中推出所有的能得到的元素B,按字典序输出即可。

思路:因为只有26个字符,因此直接循环枚举即可。

ACCode:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
   
#include<stdio.h>
#include<string.h> 
#include<math.h> 
    
#include<map>  
#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
   
#define ll long long 
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=1e2+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
 
int Vis[30],Use[30];
string F1[30],F2[30];
 
int main(){
    std::ios::sync_with_stdio(false);
    int T;cin>>T;
    while(T--){
        clean(Vis,0);clean(Use,0);
        int n,m,k;cin>>n>>m>>k;
        string U,X;
        cin>>U>>X;
        int lenU=U.size(),lenX=X.size();
        for(int i=0;i<lenX;++i) Vis[X[i]-'A']=1;
        for(int i=1;i<=k;++i){
            cin>>F1[i]>>F2[i];
        }
        int flag=1;
        while(flag){
            flag=0;
            for(int i=1;i<=k;++i){
                if(Use[i]) continue;
                int change=1;
                for(int j=0;j<F1[i].size();++j){
                    if(Vis[F1[i][j]-'A']==0){
                        change=0;break;
                    }
                }
                if(change){
                    for(int j=0;j<F2[i].size();++j){
                        Vis[F2[i][j]-'A']=1;
                    }Use[i]=1;flag=1;
                }
            }
        }
        for(int i=0;i<26;++i){
            if(Vis[i]) cout<<char(i+'A');
        }cout<<endl;
    }
}

E-物流配送(最小费用流)

题目链接:http://acm.zzuli.edu.cn/problem.php?id=2308

题目大意:略。

思路:又是一眼能够看出板子的题。一开始想着拆点建图,后来画了画,发现根本没必要,直接连就好了,赤裸裸的板子。

画图(样例):然后跑一波费用流就好了,输出最小费用。

ACCode:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
   
#include<stdio.h>
#include<string.h> 
#include<math.h> 
    
#include<map>  
#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
   
#define ll long long 
#define Pair pair<int,ll>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=1e3+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);
 
struct Node{
    int v,w,cost,nxt;
    Node(int _v=0,int _w=0,int _cost=0,int _nxt=0){
        v=_v;w=_w;cost=_cost;nxt=_nxt;
    }
};
Node Edge[MAXN<<2];
int Head[MAXN],Ecnt;
int Dis[MAXN],Vis[MAXN];
int Pre[MAXN],Flow[MAXN],Last[MAXN];
int n,S,T;
 
void Intt(){
    clean(Head,-1);Ecnt=0;
}
void Add(int u,int v,int w,int cost){
    Edge[Ecnt]=Node(v,w,cost,Head[u]);
    Head[u]=Ecnt++;
    Edge[Ecnt]=Node(u,0,-cost,Head[v]);
    Head[v]=Ecnt++;
}
int SPFA(){
    clean(Vis,0);Vis[S]=1;
    clean(Dis,INF32);Dis[S]=0;
    Flow[S]=INF32;Pre[T]=-1;
    queue<int> que;que.push(S);
    while(que.size()){
        int u=que.front();que.pop();
        Vis[u]=0;
        for(int i=Head[u];i+1;i=Edge[i].nxt){
            int temp=Edge[i].v;
            if(Edge[i].w>0&&Dis[temp]>Dis[u]+Edge[i].cost){
                Dis[temp]=Dis[u]+Edge[i].cost;
                Flow[temp]=min(Flow[u],Edge[i].w);
                Last[temp]=i;Pre[temp]=u;
                if(Vis[temp]==0){
                    Vis[temp]=1;que.push(temp);
                }
            }
        }
    }return Dis[T]==INF32?0:1;
}
void MCMF(){
    int maxw=0,mincost=0;
    while(SPFA()){
        int u=T;
        maxw+=Flow[T];
        mincost+=Dis[T]*Flow[T];
        while(u!=S){
            Edge[Last[u]].w-=Flow[T];
            Edge[Last[u]^1].w+=Flow[T];
            u=Pre[u];
        }
    }printf("%d\n",mincost);
}
int main(){
    Intt();
    scanf("%d",&n);
    int x;S=0,T=n+1;
    for(int i=1;i<=n;++i){
        scanf("%d",&x);
        Add(S,i,x,0);
    }
    for(int i=1;i<=n;++i){
        scanf("%d",&x);
        Add(i,T,x,0);
    }int a,b,v;
    for(int i=1;i<n;++i){
        scanf("%d%d%d",&a,&b,&v);
        Add(a,b,INF32,v);Add(b,a,INF32,v);
    }MCMF();
}
 
/*
 
*/

F-Gene mutation(读题+暴力)

题目链接:http://acm.zzuli.edu.cn/problem.php?id=2309

题目大意:给出n个元素的数组a,和m元素的数组b。然后判断a中有多少组连续元素能够转化成b。

能够转化的意思为:对应位置元素相减相等。顺序可以打乱。

思路:由于给定数据非常小,因此直接暴力枚举每个位置作为起点即可。对b数组进行排序,然后每组小数组也排序,比较即可。

但是由于OJ的问题(输入数据和输出数据是相同的,就写了份表面AC的代码,等有机会在测试吧)

Code:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
   
#include<stdio.h>
#include<string.h> 
#include<math.h> 
    
#include<map>  
#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
   
#define ll long long 
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=2e4+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
 
int a[MAXN],b[15],c[15];
int n,m;
 
int main(){
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=0;i<n;++i) scanf("%d",&a[i]);
        scanf("%d",&m);
        for(int i=0;i<m;++i) scanf("%d",&b[i]);
        sort(b,b+m);
//      for(int i=1;i<=m;++i) cout<<b[i]<<" ";
        int cnt=0;
        for(int i=0;i<=n-m;++i){
            for(int j=i;j<m+i;++j) c[j-i]=a[j];
            sort(c,c+m);
//          for(int j=1;j<=m;++j) cout<<c[j]<<" ";cout<<endl;
            int ad=c[0]-b[0],flag=1;
            for(int j=0;j<m;++j){
//              cout<<c[j]<<" "<<b[j]<<endl;
                if(ad!=(c[j]-b[j])){
                    flag=0;break;
                }
            }//cout<<"---"<<endl;
            if(flag) cnt++;
        }printf("%d\n",cnt);
    }
}

G-Checkpoints(最短路)

题目链接:http://acm.zzuli.edu.cn/problem.php?id=2310

题目大意:给出n个点,m个单向边,起点S和终点T,求S到T 的最短距离

思路:直接建完图之后跑Dijkstra,但是不知道为什么比赛的时候都WA了。。。

ACCode:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
   
#include<stdio.h>
#include<string.h> 
#include<math.h> 
    
#include<map>  
#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
   
#define ll long long 
#define Pair pair<int,int>
#define M_P(a,b) make_pair(a,b)
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=1e2+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);
 
struct Node{
    int v,val,nxt;
    Node(int _v=0,int _val=0,int _nxt=0){
        v=_v;val=_val;nxt=_nxt;
    }
};
Node Edge[MAXN<<2];
int Head[MAXN],Ecnt;
int Vis[MAXN],Dis[MAXN];
int n,m,S,T;
 
struct Cmp{
    int operator ()(const Pair &a,const Pair &b){
        return a.second>b.second;
    }
};
void Intt(){
    clean(Head,-1);Ecnt=0;
}
void Add(int u,int v,int val){
    Edge[Ecnt]=Node(v,val,Head[u]);
    Head[u]=Ecnt++;
}
void Dijkstra(){
    clean(Vis,0);
    clean(Dis,INF32);Dis[S]=0;
    priority_queue<Pair,vector<Pair>,Cmp> que;que.push(M_P(S,0));
    while(que.size()){
        Pair u=que.top();que.pop();
        if(Vis[u.first]) continue;
        Vis[u.first]=1;
        for(int i=Head[u.first];i+1;i=Edge[i].nxt){
            int temp=Edge[i].v;
            if(Dis[temp]>Dis[u.first]+Edge[i].val){
                Dis[temp]=Dis[u.first]+Edge[i].val;
                que.push(M_P(temp,Dis[temp]));
            }
        }
    }
}
int main(){
    int Case;scanf("%d",&Case);
    while(Case--){
        Intt();
        scanf("%d%d%d%d",&n,&m,&S,&T);
        int a,b;
        for(int i=1;i<=m;++i){
            scanf("%d%d",&a,&b);
            Add(a,b,1);
        }Dijkstra();
        printf("%d\n",Dis[T]);
    }
}
 
/*
 
*/

H-Attack City and Capture Territory(博弈)

题目链接:http://acm.zzuli.edu.cn/problem.php?id=2311

题目大意:刘备和孙权打炮台,每个炮台有a[i]滴血,一人一下(打的血量不限),最后打完的那人赢。刘备先打,问最后谁会赢)。

思路:异或和博弈。

ACCode:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
   
#include<stdio.h>
#include<string.h> 
#include<math.h> 
    
#include<map>  
#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
   
#define ll long long 
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=1e2+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
 
int a[MAXN];
 
int main(){
    int T;cin>>T;
    while(T--){
        int n;cin>>n;
        for(int i=1;i<=n;++i) cin>>a[i];
        int ans=0;
        for(int i=1;i<=n;++i) ans^=a[i];
        if(ans>0) cout<<"Liu_B is sure to win."<<endl;
        else cout<<"Liu_B is not sure to win."<<endl;
    }
     
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

猜你喜欢

转载自blog.csdn.net/qq_40482358/article/details/88960068