bestcoder 92

来源:互联网 发布:2017网络贩枪最新消息 编辑:程序博客网 时间:2024/04/28 22:48

Skip the Class

Accepts: 678
Submissions: 1285
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
终于又开学啦。呃喵最喜欢的就是开学了,因为这样她又可以愉快地翘课了(啊?)呃喵接下来有n节课程需要上(换句话说,可以翘。)每节课程有相应的课程类型与课程翘课价值。有一点需要注意的是,呃喵不可以翘同一类课程超过两次,就是如果这类课已经翘了两次,接下来就一定要上。问你在这个条件下,呃喵可以获得的最大翘课价值。
输入描述
第一行为一个整数T,代表数据组数。接下来,对于每组数据——第一行一个整数n,表示接下来需要依次上的课程数量,接下来有n行,每行包括一个仅由'a'~'z'构成的长度不超过10的字符串s与一个正整数v。其中字符串表示课程的类型,相同的字符串代表相同的课程。数据保证——1 <= T <= 1000对于每组数据,1 <= n <= 100,1 <= |s| <= 10, 1 <= v <= 1000
输出描述
对于每组数据,输出一行。该行有1个整数,表示呃喵可以获得的最大翘课价值。
输入样例
25english 1english 2english 3math 10cook 1002a 1a 2
输出样例
1153

对课程排个序,取前两名即可。
#include <iostream>#include<bits/stdc++.h>using namespace std;const int N=1100;struct node{    int v;    char s[20];}a[N];bool cmp(node a,node b){    if(strcmp(a.s,b.s)==0)    {        return a.v>b.v;    }    return strcmp(a.s,b.s)<0;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        int n;        scanf("%d",&n);        for(int i=0;i<n;i++)        {            scanf("%s%d",a[i].s,&a[i].v);        }        sort(a,a+n,cmp);        int t;        int ans=0;        for(int i=0;i<n;i++)        {            if(i==0||strcmp(a[i].s,a[i-1].s)!=0)            {                ans+=a[i].v;                t=1;            }            else if(strcmp(a[i].s,a[i-1].s)==0&&t<2)            {                t++;                ans+=a[i].v;            }        }        cout<<ans<<endl;    }}

Count the Sheep

Accepts: 227
Submissions: 805
Time Limit: 3000/1500 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
开学翘课固然快乐,然而也有让呃喵抓狂的事,那当然就是考试了!这可急坏了既要翘课又想要打BC还要准备考试的呃喵。呃喵为了准备考试没有时间刷题,想打BC又不想跌分,只得求助于BCround92的出题人snowy_smile,让他说点什么 ~~>_<~~。snowy_smile实在没有办法,但是又不好意思透题,只好告诉呃喵,当务之急是好好休息。"如果你按照下面这个办法睡着,那么第二天就绝对不会在BC的赛场上跌分——想象一片一望无际、广阔无边的青青草原,草原上住着一群羊,包括n只沉默的男羊和m只流泪的女羊,在男羊和女羊之间,存在k个朋友关系。现在你可以以任意一只羊为起点,顺着朋友关系数下去。如果能够连续数4只各不相同的羊,就能超过99%的数羊者,成功入睡。"呃喵听后十分震惊,但她还是听话地数下去,果然,数到第4只羊就睡着了,并一口气睡过了头,成功地错过了第二天的BestCoder,真的不会在BC的赛场上跌分啦!然而你,可就没有这么好的运气了,你既然看到了这第二题,自然一般已有提交,已经无法回头了。面对"不AC这题就可能跌分"窘境的你,需要说出,呃喵在睡前可能有多少种不同的数羊序列。即输出"A-B-C-D"这样序列的方案数,满足A-B、B-C、C-D是朋友关系且A、B、C、D各不相同。
输入描述
第一行输入数据组数T对于每组数据,第一行有三个整数n, m, k,表示n只男羊编号分别为1~n,m只女羊编号分别为1~m,并且存在k个朋友关系。接下来给出k行,每行给出两个数x y,表示第x只男羊和第y只女羊是朋友。数据保证——不会给出重复的朋友关系1 <= T <= 1000对于30%的数据,1 <= n, m, k <= 100对于99%的数据,1 <= n, m, k <= 1000对于100%的数据,1 <= n, m, k <= 100000
输出描述
对于每组数据,输出一行,该行包含一个整数,表示呃喵睡觉前可能数了哪4只羊的序列的方案数。
输入样例
(为了方便阅读,样例输入中数据组间中会额外添加一行空行)32 2 41 11 22 12 23 1 31 12 13 13 3 31 12 12 2
输出样例
802
Hint
第一组样例:(b1-g1-b2-g2) (b1-g2-b2-g1) (b2-g1-b1-g2) (b2-g2-b1-g1) (g1-b1-g2-b2) (g1-b2-g2-b1) (g2-b1-g1-b2) (g2-b2-g1-b1) 共8种合法序列

公羊和母羊构成一个二分图,而遍历四只不同的羊需要连续的三条线段。考虑三条线段中间的那条线段,连接两端的端点a、b,(a的度-1)*(b的度-1)等于这条线段能取得的方案数。遍历所有的关系, 把它们作为中间线段考虑即可。最后的答案*=2。时间复杂度为o(k),比题解好一些……

#include <iostream>#include<bits/stdc++.h>#define ll __int64using namespace std;const int N=110000;int dl[N],dr[N],l[N],r[N];int main(){    int T;    scanf("%d",&T);    while(T--)    {        int n,m,k;        scanf("%d%d%d",&n,&m,&k);        memset(dl,0,sizeof(dl));        memset(dr,0,sizeof(dr));        for(int i=0;i<k;i++)        {            scanf("%d%d",&l[i],&r[i]);            dl[l[i]]++;            dr[r[i]]++;        }        ll ans=0;        for(int i=0;i<k;i++)        {            ll ld=dl[l[i]],rd=dr[r[i]];            ans+=(ld-1)*(rd-1);        }        ans*=2;        printf("%I64d\n",ans);    }}

Girls Love 233

Accepts: 30
Submissions: 218
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
除了翘课以外,结识新的妹子也是呃喵重要的日程安排之一。这不,呃喵又混进了一个叫做ACgirls的女生群里,来达成自己不可描述的目的。然而,呃喵只会喵了个咪地说话,于是很容易引起注意。为了掩饰自己的真实身份,呃喵每次说话都小心翼翼。她知道,很多女生都喜欢说"233",然而呃喵想说的话一开始就确定好了,所以她要对这句话做修改。这句话的长度为n,语句里的字符不是'2'就是'3'。呃喵的智力非常有限,只有m点。她每次操作可以交换两个相邻的字符,然而代价是智力-2。现在问你,在使得自己智力不降为负数的条件下,呃喵最多能使这个字符串中有多少个子串"233"呢?如"2333"中有一个"233","232323"中没有"233"
输入描述
第一行为一个整数T,代表数据组数。接下来,对于每组数据——第一行两个整数n和m,分别表示呃喵说的字符串长度 以及呃喵的智力第二行一个字符串s,代表呃喵具体所说的话。数据保证——1 <= T <= 1000对于99%的数据,1 <= n <= 10, 0 <= m <= 20对于100%的数据,1 <= n <= 100, 0 <= m <= 100
输出描述
对于每组数据,输出一行。该行有1个整数,表示最多可使得该字符串中有多少个"233"
输入样例
36 22333236 12333237 42223333
输出样例
212

这题场上爆搜T了,之后用题解的方法过了:

首先,因为字符不是'2'就是'3',所以我们可以把字符串当做一个全部都是'3'的串,然后有若干的'2'插入到了某些位置。
显然,我们交换相邻的'2'与'2'或者相邻的'3'与'3'是没有意义的,我们只会进行相邻'2'与'3'之间的交换。因此,所有'2'的相对前后关系其实是不会变化的。
做了这些比较基础的分析之后,基于数据规模很小,我们可以用以下4个要素表示完整的状态:
1.处理到第几个'2'
2.最后一个'2'停留在什么位置,如果当前的'2'与上一个'2'距离相差>=2时则对答案+1
3.呃喵的剩余交换次数是多少
4.当前已经成功得到几个"233"
而这四个要素的大小,最坏情况下分别是n、n、m、n级别的数,我们随便以3个要素作为下标对应状态,使得第4个要素最优做DP. 转移的时候步长也是不超过2m的,所以很容易就可以得出复杂度为O(n * n * m/2 * m)的算法,这个对于本题的时限和数据,没有什么作死写法的话是可以完全无压力顺利AC的。

题解说的第二个优化方法感觉可行,在标程的代码上感觉处理的有点疑问(没看懂- -),所以放弃了。
#include <iostream>#include<bits/stdc++.h>using namespace std;const int N=105;int n,T,m,cnt2,f[N][N][N],g[N];char s[N];int v[N][N][N];//ʡȥmemsetint dfs(int num2,int lastpos,int lastm){//cout<<num2<<" "<<lastpos<<" "<<lastm<<endl;    if(num2 > cnt2)  return n-lastpos >= 2;    if(v[num2][lastpos][lastm] == T + 1)  return f[num2][lastpos][lastm];    v[num2][lastpos][lastm] = T + 1;    int l = max(lastpos + 1,g[num2] - lastm);    int r = min(n,g[num2] + lastm);    f[num2][lastpos][lastm] = -1e9;    for(int i = l;i <= r;i++)    {        int cost = abs(i - g[num2]);        int t = dfs(num2 + 1,i,lastm - cost)+(i - lastpos >= 3) * (num2 > 1);        if(t > f[num2][lastpos][lastm])            f[num2][lastpos][lastm] = t;    }    return f[num2][lastpos][lastm];}int main(){    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        m /= 2;        scanf("%s",s + 1);        cnt2 = 0;        for(int i = 1; i <= n; i++)        {            if(s[i] == '2')            {               g[++cnt2] = i;            }        }        if(cnt2 == 0) printf("0\n");        else    printf("%d\n",dfs(1,0,m));    }}



总体来说这场不难,但是太久没写题,思维不太够用。掉分伤心。


0 0
原创粉丝点击