BNU Training 2016.07.25 总结

来源:互联网 发布:sql中minus 编辑:程序博客网 时间:2024/06/06 02:11

比赛链接 https://acm.bnu.edu.cn/v3/contest_show.php?cid=8070#info

AC 5/9

A题:

      就不说题意了,递归一下,通通分就好啦。

#include<cstring>#include<cstdio>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;ll a[2][11];ll len[2];int n,m;ll gcd(ll x,ll y){    if(y==0) return x;    return gcd(y,x%y);}template<class T>void read(T&x){    char ch;bool flag;    while(!isdigit(ch=getchar())) if(ch=='-') flag=true ;    x=ch-'0';    while(isdigit(ch=getchar())) x=x*10+ch-'0';    if(flag) x=-x;}void work(int o,long long &p,long long &q,int x){    if(x==len[o])    {        p=a[o][x];        q=1;        return;    }    long long k=a[o][x];    long long xx,yy;    work(o,xx,yy,x+1);    p=k*xx+yy;    q=xx;}void Div(ll &x,ll &y){    ll G=gcd(x,y);    x/=G;    y/=G;}void Show(ll x,ll y){    if((x<0 &&y>0)||(x>0 && y<0))    {        if(x%y==0)printf("%lld",x/y);        else        {            printf("%lld",x/y-1);            x=abs(x);            y=abs(y);            x=y-x%y;        }    }    else printf("%lld",x/y);    if(x%y==0)    {        printf("\n");        return;    }    printf(" ");    Show(y,x%y);}int main(){    int cas=0;    while(scanf("%d%d",&n,&m)!=EOF)    {        ll pa,pb,qa,qb;        if(n==0 &&m==0) break;        len[0]=n;        len[1]=m;        for(int i=1;i<=n;i++)            scanf("%lld",&a[0][i]);        work(0,pa,qa,1);        for(int i=1;i<=m;i++)            scanf("%lld",&a[1][i]);        work(1,pb,qb,1);        Div(pa,qa);        Div(pb,qb);        printf("Case %d:\n",++cas);        long long x,y;        x=pa*qb+pb*qa;        y=qa*qb;        Div(x,y);        Show(x,y);        x=pa*qb-pb*qa;        y=qa*qb;        Div(x,y);        Show(x,y);        x=pa*pb;        y=qa*qb;        Div(x,y);        Show(x,y);        x=pa*qb;        y=qa*pb;        Div(x,y);        Show(x,y);    }}


B题:

大原题,折叠字符串。问折叠后的最短长度。比如abbbcdcdcdabbbcdcdcd,最短的折叠方法为2(a3b3(cd)),输出长度11。暴力dp的,还套了个KMP,应该不用套。


#include<cstring>#include<cstdio>#include<iostream>#include<algorithm>using namespace std;char s[505];int last[505];int Len[505];int dp[505][505];template<class T>void read(T&x){    char ch;    while(!isdigit(ch=getchar()));    x=ch-'0';    while(isdigit(ch=getchar())) x=x*10+ch-'0';}int get_next(int l,int r){    int j=0;    int len=r-l+1;    for(int i=1;i<=len;i++) last[i]=0;    for(int i=2;i<=len;i++)    {        while(j && s[i+l-1]!=s[j+1+l-1]) j=last[j];        if(s[i+l-1]==s[j+1+l-1]) j++;        last[i]=j;    }    if(len%(len-last[len])==0) return len/(len-last[len]);    return 0;}int calc(int l,int r){    if(l>r) return 0;    if(dp[l][r]!=-1) return dp[l][r];    int &ans=dp[l][r];    int len=r-l+1;    ans=len;    int k=get_next(l,r);    if(k)    {        if(k==len) ans=min(ans,Len[k]+1);        else ans=min(ans,Len[k]+2+calc(l,l+len/k-1));    }    for(int i=l;i<r;i++)        ans=min(ans,calc(l,i)+calc(i+1,r));    return ans;}int main(){    for(int i=1;i<=9;i++) Len[i]=1;    for(int i=10;i<=99;i++) Len[i]=2;    for(int i=100;i<=500;i++) Len[i]=3;    int cas=0;    int n;    while(scanf("%s",s+1)!=EOF)    {        if(s[1]=='0') return 0;        memset(dp,-1,sizeof(dp));        n=strlen(s+1);        printf("Case %d: %d\n",++cas,calc(1,n));    }}

C题:

模拟,最关键还是要读懂题=、=

#include<cstring>#include<cstdio>#include<iostream>#include<algorithm>#include<vector>using namespace std;typedef long long ll;struct node{    int x,y;    int dx,dy;    int valx,valy;    node() {}    node(int x_,int y_,int dx_,int dy_,int valx_,int valy_)    {        x=x_;        y=y_;        dx=dx_;        dy=dy_;        valx=valx_;        valy=valy_;    }};vector<node> card,can_use;int b[10];int a[10][10];int score[7][7][7][7][7];int ans;int work(){    sort(b+1,b+6);    if(b[1]==b[2] && b[1]==b[3] && b[1]==b[4] && b[1]==b[5]) return 50;    for(int i=1; i<=2; i++)        if(b[i+1]==b[i] && b[i+2]==b[i] && b[i+3]==b[i]) return 4*b[i];    if(b[2]==b[3] && b[3]==b[4]) return 3*b[2];    if(b[1]==b[2] && b[2]==b[3])    {        if(b[4]==b[5]) return 25;        else return 3*b[1];    }    if(b[3]==b[4] && b[4]==b[5])    {        if(b[1]==b[2]) return 25;        else return 3*b[3];    }    if(b[1]+1==b[2] && b[2]+1==b[3] && b[3]+1==b[4] && b[4]+1==b[5]) return 40;    if(b[1]+1==b[2] && b[2]+1==b[3] && b[3]+1==b[4]) return 30;    if(b[1]+1==b[2] && b[2]+1==b[3] && b[3]+1==b[5]) return 30;    if(b[1]+1==b[2] && b[2]+1==b[4] && b[4]+1==b[5]) return 30;    if(b[2]+1==b[3] && b[3]+1==b[4] && b[4]+1==b[5]) return 30;    return 0;}void pre(){    for(int i=1; i<=6; i++)        for(int j=1; j<=6; j++)            for(int k=1; k<=6; k++)                for(int l=1; l<=6; l++)                    for(int o=1; o<=6; o++)                    {                        b[1]=i;                        b[2]=j;                        b[3]=k;                        b[4]=l;                        b[5]=o;                        score[i][j][k][l][o]=work();                    }}int calc(){    int ans=0;    int same=0;    for(int i=1; i<=5; i++)    {        if(a[i][1]==a[i][2] && a[i][1]==a[i][3] && a[i][1]==a[i][4] && a[i][1]==a[i][5]) same++;        ans+=score[ a[i][1] ][ a[i][2] ][ a[i][3] ][ a[i][4] ][ a[i][5] ];    }    for(int i=1; i<=5; i++)    {        if(a[1][i]==a[2][i] && a[1][i]==a[3][i] && a[1][i]==a[4][i] && a[1][i]==a[5][i]) same++;        ans+=score[ a[1][i] ][ a[2][i] ][ a[3][i] ][ a[4][i] ][ a[5][i] ];    }    if(a[1][1]==a[2][2] && a[1][1]==a[3][3] && a[1][1]==a[4][4] && a[1][1]==a[5][5]) same++;    ans+=score[ a[1][1] ][ a[2][2] ][ a[3][3] ][ a[4][4] ][ a[5][5] ];    if(a[1][5]==a[2][4] && a[1][5]==a[3][3] && a[1][5]==a[4][2] && a[1][5]==a[5][1]) same++;    ans+=score[ a[1][5] ][ a[2][4] ][ a[3][3] ][ a[4][2] ][ a[5][1] ];    if(same==0) return ans;    return ans+(same-1)*50;}bool used[10][10];int main(){    pre();    int sk;    scanf("%d",&sk);    for(int cas=1; cas<=sk; cas++)    {        char opt[3];        int x,y;        memset(a,0,sizeof(a));        memset(used,0,sizeof(used));        card.clear();        card.push_back(node(0,0,0,0,0,0));        for(int i=1; i<=5; i++)            for(int j=1; j<=5; j++)                if(!a[i][j])                {                    scanf("%s",opt);                    if(opt[0]=='V')                    {                        scanf("%d%d",&x,&y);                        a[i][j]=x;                        a[i+1][j]=y;                        used[x][y]=used[y][x]=true;                        card.push_back(node(i,j,1,0,x,y));                    }                    else if(opt[0]=='H')                    {                        scanf("%d%d",&x,&y);                        a[i][j]=x;                        a[i][j+1]=y;                        used[x][y]=used[y][x]=true;                        card.push_back(node(i,j,0,1,x,y));                    }                    else                    {                        scanf("%d",&x);                        a[i][j]=x;                    }                }        can_use.clear();        can_use.push_back(node(0,0,0,0,0,0));        for(int i=1; i<=6; i++)            for(int j=i; j<=6; j++)                if(!used[i][j])                    can_use.push_back(node(0,0,0,0,i,j));        ans=calc();        for(int i=1; i<=12; i++)        {            for(int j=1; j<=9; j++)            {                int x=card[i].x;                int y=card[i].y;                a[x][y]=can_use[ j ].valx;                a[x+card[i].dx][y+card[i].dy]=can_use[ j ].valy;                ans=max(ans,calc());                a[x][y]=can_use[ j ].valy;                a[x+card[i].dx][y+card[i].dy]=can_use[ j ].valx;                ans=max(ans,calc());                a[x][y]=card[i].valx;                a[x+card[i].dx][y+card[i].dy]=card[i].valy;            }        }        printf("Case %d: %d\n",cas,ans);    }}


E题:

不知道为什么可以转化成二分图最大权匹配...有必要再想想


#include<cstring>#include<iostream>#include<cstdio>#include<algorithm>using namespace std;#define N 205const int INF=0x3f3f3f3f;int nx,ny,n;int g[N][N];int linker[N],lx[N],ly[N];int slack[N];bool visx[N],visy[N];bool dfs(int x){    visx[x]=true;    for(int y=0; y<ny; y++)    {        if(visy[y]) continue;        int tem=lx[x]+ly[y]-g[x][y];        if(tem==0)        {            visy[y]=true;            if(linker[y]==-1 || dfs(linker[y]))            {                linker[y]=x;                return true;            }        }        else if(slack[y]>tem)            slack[y]=tem;    }    return false;}int KM(){    memset(linker,-1,sizeof(linker));    memset(ly,0,sizeof(ly));    for(int i=0; i<nx; i++)    {        lx[i]=-INF;        for(int j=0; j<ny; j++)            if(g[i][j]>lx[i])                lx[i]=g[i][j];    }    for(int x=0; x<nx; x++)    {        for(int i=0; i<ny; i++)            slack[i]=INF;        while(true)        {            memset(visx,0,sizeof(visx));            memset(visy,0,sizeof(visy));            if(dfs(x)) break;            int d=INF;            for(int i=0; i<ny; i++)                if(!visy[i] && d>slack[i])                    d=slack[i];            for(int i=0; i<nx; i++)                if(visx[i])                    lx[i]-=d;            for(int i=0; i<ny; i++)                if(visy[i]) ly[i]+=d;                else slack[i]-=d;        }    }    int res=0;    for(int i=0; i<ny; i++)        if(linker[i]!=-1)            res+=g[linker[i]][i];    return res;}int main(){    int cas=0,sk;    scanf("%d",&sk);    while(sk--)    {        scanf("%d",&n);        for(int i=0;i<n;i++) g[i][i]=-INF;        for(int i=0; i<n; i++)            for(int j=i+1; j<n; j++)            {                int x;                scanf("%d",&x);                g[j][i]=g[i][j]=-x;            }        nx=ny=n;        printf("Case %d: %d\n",++cas,-KM());    }}/*2410 20 1010 2010415 20 1010 2015*/


0 0
原创粉丝点击