CUGBACM Codeforces Tranning 8解题报告

来源:互联网 发布:微信幼儿网络教育 编辑:程序博客网 时间:2024/04/29 07:38

比赛链接点击打开链接

A题 

题意 给定一个由左右小括弧组成的串,通过删除某些括弧,求剩下的括弧能够获得的最长合法长度。

思路:类似求合法括弧的题目,之前做过一些,也有了一些经验。首先,从左往右扫,两个变量rest和cnt ,遇到“(” ,rest++,否则rest--,cnt++。若rest<0 说明这个括弧要删除。同理,从右往左再扫一遍。求两次的最大值即可。

开始的时候没读清题意,以为是老题WA了。。。

AC代码

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<cmath>#include<iomanip>#include<algorithm>#include<queue>#include<map>#include<set>using namespace std;#define pi acos(-1.0)#define eps 1e-6typedef long long ll ;const int inf = 1<<29;char a[1000005];int main(){    cin>>a;    int n=strlen(a),i;    int cnt1=0,cnt2=0;    int rest=0;    for(i=0; i<n; i++)    {        if(a[i]=='(')        {            rest++;        }        else if(a[i]==')')        {            rest--;            if(rest>=0)            {                cnt1++;            }        }        if(rest<0)        {            rest=0;        }    }    rest=0;    for(i=n-1; i>=0; i--)    {        if(a[i]==')')        {            rest++;        }        else if(a[i]=='(')        {            rest--;            if(rest>=0)            {                cnt2++;                rest--;            }        }        if(rest<0)        {            rest=0;        }    }    cout<<max(cnt1,cnt2)*2<<endl;    return 0;}

B题

题意:给定一个矩阵d,d[i][j]代表初始i和j之间的最短路。现在要在某些点间建一些新的路径。求建到第i条路径时,任意两点之间最短路的和。

用类似floyed求最短路的思想。简单回顾一下floyed求最短路。其基本思想是dp,对于从i到j的路径,走点k和不走点k。那么这道题从i到j,对于新建的路,走还是不走。

注意输入数据中,新建的路有可能比之前的路要长。

AC代码

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<cmath>#include<iomanip>#include<algorithm>#include<queue>#include<map>#include<set>using namespace std;#define pi acos(-1.0)#define eps 1e-6typedef long long ll ;const int inf = 1<<29;const int maxn=305;int d[maxn][maxn];int main(){    int n,m,i,j,a,b,c;    cin>>n;    for(i=1;i<=n;i++)    {        for(j=1;j<=n;j++)            cin>>d[i][j];    }    cin>>m;    while(m--)    {        cin>>a>>b>>c;        for(i=1;i<=n;i++)        {            for(j=1;j<=n;j++)            {                d[j][i]=d[i][j]=min(d[i][j],d[i][a]+d[b][j]+c);                d[j][i]=d[i][j]=min(d[i][j],d[i][b]+d[a][j]+c);            }        }        ll ans=0;        for(i=1;i<=n;i++)        {            for(j=i+1;j<=n;j++)            {                ans+=d[i][j];            }        }        cout<<ans<<" ";    }    return 0;}

C题 

题意 输入一些路径。让你删除一些路径的同时再添加一些路径,使得每两个点之间都可以到达。

思路:并查集。输入路径时,判断两点是否处于同一个集合,若在,当前这条路就可以删除。否则,这条路径就要保留。

然后再枚举两个任意点,判断是否在同一个集合中,若不在,两个点之间建路。

AC代码

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<cmath>#include<iomanip>#include<algorithm>#include<queue>#include<map>#include<set>using namespace std;#define pi acos(-1.0)#define eps 1e-6typedef long long ll ;const int inf = 1<<29;const int maxn=1005;int del[maxn][2],add[maxn][2];int parent[maxn];void init(int n){    for(int i=1;i<=n;i++)        parent[i]=i;}int find_p(int p){    if(p==parent[p]) return p;    return parent[p]=find_p(parent[p]);}int main(){    int n,i,j,x,y,cnt1=0,cnt2=0;    cin>>n;    init(n);    for(i=1;i<n;i++)    {        cin>>x>>y;        int fx=find_p(x),fy=find_p(y);        if(fx!=fy)            parent[fx]=fy;        else        {            del[cnt1][0]=x,del[cnt1++][1]=y;        }    }    for(i=1;i<=n;i++)    {        for(j=i+1;j<=n;j++)        {             int fi=find_p(i),fj=find_p(j);             if(fi!=fj)             {                 parent[fi]=fj;                 add[cnt2][0]=fi,add[cnt2++][1]=fj;             }        }    }    cout<<cnt1<<endl;    for(i=0;i<cnt1;i++)    {        cout<<del[i][0]<<" "<<del[i][1]<<" "<<add[i][0]<<" "<<add[i][1]<<endl;    }    return 0;}


D题 机智题

题意:为了说清楚题意,我增加一个时间t。题意是这样的:t=0时,有零个朋友的人全部滚蛋。t=1时,对于剩下的人而言,有1个朋友的全部滚蛋……问最终人数稳定时,最多可能剩下多少人。

思路:因为时间是每次加1的。对于当前t,认识t+1个朋友的不会离开。这些人要想在t+1秒不离开,他们认识的人数就要发生突变,必然变成比t+1小的数,显然t-1是最大的数。对于n个人来说,显然n-2最大。那么怎么实现这种突变呢?假设1,2不认识,并且与n-2个人都认识,剩下n-2个人认识n-1个人,那么当t=n-2时,1和2走了,那么剩下的n-2个人瞬间从认识n-1个人变成认识n-3个人。当t=n-1时,已经没有认识n-1个人的人了。

因此,最终结果就是n-2,特判一下1就好。

AC代码

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<cmath>#include<iomanip>#include<algorithm>#include<queue>#include<map>#include<set>using namespace std;#define pi acos(-1.0)#define eps 1e-6typedef long long ll ;const int inf = 1<<29;int main(){    int n;    int t;    cin>>t;    while(t--)    {        cin>>n;        if(n==1) cout<<0<<endl;        else cout<<n-2<<endl;    }    return 0;}

E题

先来WA个坑。。。

0 0