现在的位置: 首页 > 综合 > 正文

130825周赛解题报告

2018年02月21日 ⁄ 综合 ⁄ 共 6770字 ⁄ 字号 评论关闭

题目整体不难,很多都可以暴力直接做,但是除去比赛时做出来的五道题之外剩下的代码量都比较高,写的比较艰难。

A:Babs' Box Boutique

传送门

题意是问怎么塞盒子可以塞的数量最多(只考虑底边符合,三边可以旋转)

因为n<=10,所以果断排序后DFS暴搜,简单过

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>

using namespace std;

struct node
{
    int a;
    int b;
    int c;
} s[1005];

int n;
int ans;
int used[1005];

void DFS(int ax,int ay,int k,int t)
{
    if(t>ans)
    {
        ans=t;
    }
    for(int i=0; i<n; i++)
    {
        if(used[i]==0)
        {
            if(s[i].a>=ax&&s[i].b>=ay)
            {
                used[i]=1;
                DFS(s[i].a,s[i].b,k+1,t+1);
                used[i]=0;
            }
            else if(s[i].a>=ax&&s[i].c>=ay)
            {
                used[i]=1;
                DFS(s[i].a,s[i].c,k+1,t+1);
                used[i]=0;
            }
            else  if(s[i].b>=ax&&s[i].c>=ay)
            {
                used[i]=1;
                DFS(s[i].b,s[i].c,k+1,t+1);
                used[i]=0;
            }
        }
    }
}

int main()
{
    int counter = 0;
    while(scanf("%d",&n)!=EOF)
    {
        counter++;
        if(n==0)  break;
        memset(used,0,sizeof(used));
        int aa,bb,cc;
        int t[4];
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<3; j++)
            {
                scanf("%d",&t[j]);
            }
            sort(t,t+3);
            s[i].a=t[0];
            s[i].b=t[1];
            s[i].c=t[2];
        }
        ans=0;
        DFS(0,0,0,0);
        printf("Case %d: %d\n",counter,ans);
    }
    return 0;
}

B:Flash Mob

传送门

求离给出所有点的曼哈顿距离最近的点,因为是曼哈顿距离所以X,Y可以分开计算,并且最近的点必然在已有点中间,进一步能退出肯定是中间的点

这样子题目就很好写了。

我写的是狂搜,效率不是很高,回头改一下

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>

using namespace std;

int n;
int x[1005],y[1005];
int sumx,sumy,weix,weiy,xx,xy;

bool cmp(int a,int b)
{
    return a < b;
}

int main()
{
    int counter = 0;
    while(scanf("%d",&n) != EOF)
    {
        counter++;
        if(n == 0) break;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&x[i],&y[i]);
        }
        sort(x,x+n,cmp);
        sort(y,y+n,cmp);
        sumx = 0;
        sumy = 0;
        weix = x[0];
        weiy = y[0];
        for(int i=0;i<n;i++)
        {
            sumx += abs(x[i] - weix);
            sumy += abs(y[i] - weiy);
        }
        xx = sumx;
        xy = sumy;
        //cout<<x[0]<<' '<<y[0]<<endl;
        //cout<<sumx<<' '<<sumy<<endl;
        for(int i=1;i<n;i++)
        {
            xx = xx + (i) * (x[i] - x[i-1]) - (n - i) * (x[i] - x[i-1]);
            xy = xy + (i) * (y[i] - y[i-1]) - (n - i) * (y[i] - y[i-1]);
            //cout<<x[i]<<' '<<y[i]<<endl;
            //cout<<xx<<' '<<xy<<endl;
            if(xx < sumx)
            {
                sumx = xx;
                weix = x[i];
            }
            if(xy < sumy)
            {
                sumy = xy;
                weiy = y[i];
            }
        }
        printf("Case %d: (%d,%d) %d\n",counter,weix,weiy,sumx+sumy);
    }
}

C:Hexagon Perplexagon

给出七个正六边形,要求能凑出左边哪个造型(相邻边上的数字相同)

因为给出限定最上面哪个和中间的那个相邻的必须是1,所以计算量直接压缩到7!

在加上相邻边之间有规律(与中间相邻的数其前面一个数必然属于后一个六边形,后一个必然属于前一个六边形

所以if一下很快就出来了

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>

using namespace std;

int s[20][20],f[20][20];
int k[20],l[20];
bool used[20];
bool usedans;

void dfs(int x)
{
    for(int i=0; i<7;i++)
    {
        if(used[i] == false)
        {
            k[x]=i;
            if(x==0)
            {
                l[0]=f[k[0]][1];
            }
            else
            {
                int t=s[k[0]][l[0]+x-1];
                l[x]=f[k[x]][t];
                if(x>1&&s[k[x-1]][l[x-1]+5]!=s[k[x]][l[x]+1])
                {
                    continue;
                }
                if(x==6&&s[k[x]][l[x]+5]==s[k[1]][l[1]+1])
                {
                    usedans=true;
                }
            }
            used[i]=true;
            if(x<6)
            {
                dfs(x+1);
            }
            used[i]=false;
            if(usedans == true)
            {
                return ;
            }
        }
    }
}
int main()
{
    int T,counter = 0;
    scanf("%d",&T);
    while(T--)
    {
        counter++;
        for(int i=0; i<7;i++)
        {
            for(int j=0; j<6;j++)
            {
                scanf("%d",&s[i][j]);
                s[i][j+6]=s[i][j];
                f[i][s[i][j]]=j;
            }
        }
        usedans=false;
        memset(used,false,sizeof(used));
        dfs(0);
        printf("Case %d:",counter);
        if(usedans)
        {
            for(int i=0; i<=6;i++)
            {
                printf(" %d",k[i]);
            }
            printf("\n");
        }
        else
        {
            printf(" No solution\n");
        }
    }
    return 0;
}

D:I've Got Your Back(gammon)

传送门

题目告诉我们不超过15504

那么就按照不超过15504打表

很快就过了

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>

using namespace std;

int s[10][16000];

void get()
{
    s[1][0] = s[2][0] = s[3][0] = s[4][0] = s[5][0] = 0;
    s[6][0] = 15;
    for(int i = 1; i < 15504; i++)
    {
        for(int j=1; j<=5; j++)
        {
            s[j][i] = s[j][i-1];
        }
        if(s[6][i-1] != 0)
        {
            s[6][i] = s[6][i-1] - 1;
            s[5][i] = s[5][i-1] + 1;
        }
        else
        {
            int t = 5;
            while(s[t][i-1] == 0)
            {
                t--;
            }
            s[t][i] = 0;
            s[t-1][i] = s[t-1][i-1] + 1;
            s[6][i] = s[t][i-1] - 1;
        }
    }
}

int main()
{
    get();
    char c;
    int q[10];
    int a,counter = 0;
    while(scanf("%c",&c) != EOF)
    {
        if(c == 'e') break;
        counter++;
        printf("Case %d: ",counter);
        if(c == 'm')
        {
            for(int i=1; i<=6; i++)
            {
                scanf("%d",&q[i]);
            }
            int w;
            for(int i=0;i<15504;i++)
            {
                w = 0;
                for(int j=1;j<=6;j++)
                {
                    if(s[j][i] != q[j])
                    {
                        w = 1;
                        break;
                    }
                }
                if(w == 0)
                {
                    printf("%d\n",i);
                    break;
                }
            }
        }
        if(c == 'u')
        {
            scanf("%d",&a);
            printf("%d",s[1][a]);
            for(int i=2;i<=6;i++)
            {
                printf(" %d",s[i][a]);
            }
            printf("\n");
        }
        getchar();
    }
}

E:Parencedence!

传送门

题目略麻烦

求两个人对一个已经有的式子加括号,A使式子变大B使式子变小,问谁胜

因为只有+-*三个符号,所以问题不是很大,单纯DFS计算就行了,就是代码量略长,含符号的数据记录问题略多,写的很伤心

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>

using namespace std;

#define INF 1000000007

int rval[11], n;
char ss[12][5];
int rop[11];
typedef pair<int, int> P;
int getval(int x, int y, char c)
{
    if(c == '+')
    {
        return x + y;
    }
    if(c == '*')
    {
        return x * y;
    }
    return x - y;
}

P get(int val[], int op[], int deep, int flag)
{
    P ans;
    if(deep == 0)
    {
        ans.first = val[0];
        ans.second = -1;
        return ans;
    }
    if(flag)
    {
        ans.first = -INF;
    }
    else
    {
        ans.first = INF;
    }
    for(int i = 0; i < deep; i++)
    {
        int x = getval(val[i], val[i + 1], ss[op[i]][0]);
        int cnt = 0;
        int tmpop[11], tmpval[11];
        for(int j = 0; j <= deep; j++)
        {
            if(j == i)
            {
                continue;
            }
            if(j == i + 1)
            {
                tmpval[cnt++] = x;
            }
            else
            {
                tmpval[cnt++] = val[j];
            }
        }
        cnt = 0;
        for(int j = 0; j < deep; j++)
        {
            if(j == i)
            {
                continue;
            }
            else
            {
                tmpop[cnt++] = op[j];
            }
        }
        P tmp = get(tmpval, tmpop, deep - 1, !flag);
        if(flag)
        {
            if(tmp.first > ans.first)
            {
                ans.first = tmp.first;
                ans.second = i;
            }
        }
        else
        {
            if(tmp.first < ans.first)
            {
                ans.first = tmp.first;
                ans.second = i;
            }
        }
    }
    return ans;
}

int main()
{
    int T, counter = 0;
    scanf("%d", &T);
    while(T--)
    {
        counter++;
        scanf("%d", &n);
        for(int i = 0; i < n; i++) scanf("%d%s", &rval[i], ss[i]);
        for(int i = 0; i < n; i++) rop[i] = i;
        scanf("%d", &rval[n]);
        P ansx = get(rval, rop, n, 1);
        P ansy = get(rval, rop, n, 0);
        printf("Case %d:\n", counter);
        printf("Player 1 (%d%s%d) leads to %d\n", rval[ansx.second], ss[ansx.second], rval[ansx.second + 1], ansx.first);
        printf("Player 2 (%d%s%d) leads to %d\n", rval[ansy.second], ss[ansy.second], rval[ansy.second + 1], ansy.first);
        if(ansx.first > -ansy.first)
        {
            printf("Player 1 wins\n");
        }
        else if(ansx.first < -ansy.first)
        {
            printf("Player 2 wins\n");
        }
        else
        {
            printf("Tie\n");
        }
    }
    return 0;
}

G:Show Me the Money

传送门

当时看到这题目的时候第一反应是这竟然是星际1的加钱秘籍!(想太多了)

这题是要求一个最相近汇率,换个想法也就是求最短路,既然是最短路果断floyd上,注意一下数据全是整数就行了

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <cmath>
#include <map>
using namespace std;
map<string,int>q;
string ss[11];
long long a[33][33];
int ans,m;
string p1,p2,p;
void f()
{
    int i,j,k,id,num,l;
    long long sum=-1,in,aa,bb;
    char h[22];
    for(i=1; i<=ans; ++i)
    {
        for(j=1; j<=ans; ++j)
        {
            if(i!=j)
            {
                for(k=1; k<=ans; ++k)
                {
                    if(i!=k&&j!=k)
                    {
                        if(a[j][i]==0||a[i][j]==0)
                        {
                            continue;
                        }
                        if(a[j][k]!=0)
                        {
                            continue;
                        }
                        a[j][k]=a[j][i]*a[i][k];
                        a[k][j]=a[k][i]*a[i][j];
                    }
                }
            }
        }
    }
    id=q[p];
    for(i=1; i<=ans; ++i)
    {
        if(i!=id&&a[i][id]!=0)
        {
            in=(long long)m*a[i][id]/a[id][i];
            if(in*a[id][i]<(long long)m*a[i][id])
            {
                in++;
            }
            if(in<=100000)
            {
                if(sum==-1||in*a[id][i]*bb<sum*aa*a[i][id])
                {
                    sum=in;
                    num=i;
                    aa=a[id][i];
                    bb=a[i][id];
                }
            }
        }
    }
    l=ss[num].size();
    for(i=0; i<l; ++i)
    {
        h[i]=ss[num][i];
    }
    h[l]=0;
    printf("%lld %s\n",sum,h);
}
int main()
{
    int t,i,cas=0,x,y;
    char s[11],s1[11],s2[11];
    while(scanf("%d",&t))
    {
        if(t==0)
        {
            break;
        }
        cas++;
        q.clear();
        ans=0;
        memset(a,0,sizeof(a));
        while(t--)
        {
            scanf("%d%s%s%d%s",&x,s1,s,&y,s2);
            p1.assign(s1);
            p2.assign(s2);
            if(q[p1]==0)
            {
                q[p1]=++ans;
            }
            ss[q[p1]]=p1;
            if(q[p2]==0)
            {
                q[p2]=++ans;
            }
            ss[q[p2]]=p2;
            a[q[p1]][q[p2]]=x;
            a[q[p2]][q[p1]]=y;
        }
        scanf("%d%s",&m,s);
        printf("Case %d: ",cas);
        p.assign(s);
        f();
    }
    return 0;
}

抱歉!评论已关闭.