2012-2013 ACM-ICPC East Central North America Regional Contest (ECNA 2012)

来源:互联网 发布:vue.js createelement 编辑:程序博客网 时间:2024/05/21 14:54

训练感想

从今天开始,HIT_Foodie队就进入了系统训练的阶段,也开始为上海大都会站的比赛开始做准备了。队里三个人,我最弱! 所以以后我一定会好好训练,争取不拖两位大爷的后腿!
今天的题难度就是regional难度,训练的时候因为一个浮点误差的问题调试了很长时间。所以接下来总结一番,并且补上没做的题。

题目分析

先把题目放出来,然后是Gym地址。

A题 Babs’ Box Boutique

题意

给n(n<10)个长方体,把这些长方体按照顺序叠放起来,注意叠放的时候,接触面要严格保持小于关系,(x <= a && y <= b) || (x <= b && y <= a)
直接搜索即可,tomriddly同学貌似忘了回溯,WA了一发。

/* written by tomriddly */#include <bits/stdc++.h>using namespace std;int n;struct Box{    int b[3];    inline void get()    {        scanf("%d%d%d", b + 0, b + 1, b + 2);    }}a[11];int ans = 0;bool vis[11];inline bool check(const int &x, const int &y, const int &a, const int &b){    return (x <= a && y <= b) || (x <= b && y <= a);}inline void dfs(const Box &last, const int &x, const int &y, const int &depth){    if (ans < depth)        ans = depth;    for (int i = 1; i <= n; i++)        if (!vis[i])        {            vis[i] = true;            if (check(a[i].b[0], a[i].b[1], last.b[x], last.b[y]))                dfs(a[i], 0, 1, depth + 1);            if (check(a[i].b[0], a[i].b[2], last.b[x], last.b[y]))                dfs(a[i], 0, 2, depth + 1);            if (check(a[i].b[2], a[i].b[1], last.b[x], last.b[y]))                dfs(a[i], 2, 1, depth + 1);            vis[i] = false;        }}int main(){    int cas = 0;    while (~scanf("%d", &n) && n)    {        ans = 0;        memset(vis, false, sizeof(vis));        for (int i = 1; i <= n; i++)            a[i].get();        for (int i = 1; i <= n; i++)        {            vis[i] = true;            dfs(a[i], 0, 1, 1);            dfs(a[i], 0, 2, 1);            dfs(a[i], 2, 1, 1);            vis[i] = false;        }        printf("Case %d: %d\n", ++cas, ans);    }    return 0;}

B题 Flash Mob

题意

给一些点的坐标,求出到这些点的曼哈顿距离之和最小,且横竖坐标均最小的点的坐标及他们的曼哈顿距离之和
把给的x坐标排序,y坐标排序,各自选取中位数即可。注意偶数个的时候选取n/2的值

/* written by jiefangxuanyan */#include <cstdio>#include <algorithm>const int N=1100;int xs[N],ys[N];int main(){    int cn=0;    while(true){        int n;        scanf("%d",&n);        if(!n){            return 0;        }        for(int i=0;i<n;i++){            scanf("%d%d",xs+i,ys+i);        }        std::sort(xs,xs+n);        std::sort(ys,ys+n);        int xm=xs[(n-1)/2],ym=ys[(n-1)/2];        int s=0;        for(int i=0;i<n;i++){            s+=std::abs(xs[i]-xm);        }        for(int i=0;i<n;i++){            s+=std::abs(ys[i]-ym);        }        printf("Case %d: (%d,%d) %d\n",++cn,xm,ym,s);    }}

C题 Hexagon Perplexagon

题意

这题有点恶心,题意就不解释了,算是一个搜索。
我们直接用next_permutation()居然 TLE 了
然后安神展开了一番剪枝,终于过了。

#include <cstdio>#include <algorithm>int in[10][10];void rotate(int *h,int tgt,int pos){    for(int i=0;i<6;i++){        if(h[i]==tgt){            int tmp[10];            for(int j=0;j<6;j++){                tmp[(pos+j)%6]=h[(i+j)%6];            }            for(int j=0;j<6;j++){                h[j]=tmp[j];            }            return;        }    }}/*bool validate(const int *put){    rotate(in[put[0]],1,0);    for(int i=0;i<6;i++){        rotate(in[put[i+1]],in[put[0]][i],(i+3)%6);    }    for(int i=0;i<6;i++){        if(in[put[i+1]][(i+2)%6]!=in[put[(i+1)%6+1]][(i+5)%6]){            return false;        }    }    return true;}*/bool dfs(int *perm,int pos){    if(pos==1){        rotate(in[perm[0]],1,0);    } else if(pos>1){        rotate(in[perm[pos-1]],in[perm[0]][pos-2],(pos+1)%6);        if(pos>2&&in[perm[pos-1]][(pos+2)%6]!=in[perm[pos-2]][(pos+5)%6]){            return false;        }    }    if(pos==7){        return in[perm[1]][4]==in[perm[6]][1];    }    for(int i=pos;i<7;i++){        std::swap(perm[pos],perm[i]);        if(dfs(perm,pos+1)){            return true;        }    }    for(int i=pos;i+1<7;i++){        std::swap(perm[i],perm[i+1]);    }    return false;}int main(){    int cn;    scanf("%d",&cn);    for(int ci=1;ci<=cn;ci++){        for(int i=0;i<7;i++){            for(int j=0;j<6;j++){                scanf("%d",in[i]+j);            }        }        int perm[10]/*={3,0,5,6,1,4,2}*/;        for(int i=0;i<7;i++){            perm[i]=i;        }        printf("Case %d:",ci);        /*do{            if(validate(perm)){                goto lblSucc;            }        } while(std::next_permutation(perm,perm+7));*/        if(dfs(perm,0)){            for(int i=0;i<7;i++){                printf(" %d",perm[i]);            }            putchar('\n');        } else{            puts(" No solution");        }    }    return 0;}

D题 I’ve Got Your Back(gammon)

题意

给一个六位的序列,要求各位之和加起来是15。这样的序列一共有15504个。
把这些序列按照字典序排序,给定两种查询。1是查询第几个序列是什么,2是查询某个序列的序号是多少。
直接生成所有的序列,用map映射一下就可以了。

/* written by tomriddly */#include <bits/stdc++.h>using namespace std;struct Fuck{    int a[7];    inline friend bool operator <(const Fuck &x, const Fuck &y)    {        for (int i = 1; i <= 6; i++)            if (x.a[i] != y.a[i])                return x.a[i] < y.a[i];        return false;    }    inline friend bool operator ==(const Fuck &x, const Fuck &y)    {        for (int i = 1; i <= 6; i++)            if (x.a[i] != y.a[i])                return false;        return true;    }}a[15555];int tmp[7], cnt = 0, n;char cmd[11];map<Fuck, int> r;inline void dfs(int depth, int presum){    if (depth == 6)    {        int sum = 0;        for (int i = 1; i <= 6; i++)            sum += tmp[i];        if (sum == 15)        {            for (int i = 1; i <= 6; i++)                a[cnt].a[i] = tmp[i];            cnt++;        }        return ;    }    for (int i = 0; i <= 15 - presum; i++)    {        tmp[depth + 1] = i;        dfs(depth + 1, presum + i);    }}int main(){    int cas = 0;    dfs(0, 0);    //cout << cnt << endl;    sort(a, a + cnt);    /*    for (int i = 0; i < cnt; i++)    {        for (int j = 1; j <= 6; j++)        {            printf("%d%c", a[i].a[j], j == 6 ? '\n' : ' ');        }        system("pause");    }    */    for (int i = 0; i < cnt; i++)        r[a[i]] = i;    while (~scanf("%s", cmd) && cmd[0] != 'e')    {        if (cmd[0] == 'm')        {            for (int i = 1; i <= 6; i++)                scanf("%d", &a[15550].a[i]);            printf("Case %d: %d\n", ++cas, r[a[15550]]);        }        else        {            int x;            scanf("%d", &x);            printf("Case %d:", ++cas);            for (int i = 1; i <= 6; i++)                printf(" %d", a[x].a[i]);            putchar('\n');        }    }    return 0;}

E题 Parencedence!

占坑,会了在写。
应该是个对抗搜索,代码没时间写了。


F题 Road Series

先占着坑,等我看明白了再写。。。

/* written by jiefangxuanyan */#include <cstdio>#include <cstring>#include <algorithm>const int LEN=1100,MAXN=100000000;char in[LEN];int storage[LEN*10];bool has[MAXN];int main(){    int cn;    scanf("%d",&cn);    for(int ci=1;ci<=cn;ci++){        int n,w;        scanf("%d%d ",&n,&w);        int pos=1;        memset(has,0,sizeof(has));        has[0]=true;        int maxSeen=0;        for(int i=0;i<n;i++){            gets(in);            int cnt=0;            for(char *p=in;*p;p++){                int cur=0,i=0;                while(true){                    storage[cnt++]=cur;                    if(cur<MAXN&&'0'<=p[i]&&p[i]<='9'){                        cur=cur*10+p[i]-'0';                        i++;                    } else{                        break;                    }                }            }            std::sort(storage,storage+cnt);            for(int i=0;i<cnt;i++){                if(storage[i]<pos+w){                    maxSeen=std::max(storage[i],maxSeen);                    has[storage[i]]=true;                    while(has[pos]){                        pos++;                    }                }            }        }        printf("Case %d: %d %d\n",ci,pos-1,maxSeen);    }    return 0;}

G题 Show Me the Money

题意

着重讲一下这道题。我们一上来就用了分数类,希望能够避免坑爹的浮点数误差。但是没有想到,使用long long竟然爆了。。。
没有办法,我们改成double,但是还是WA了。经过一番思想斗争,我们决定把代码改成java高精度!可惜的是,这回不是WA了,而是 TLE。。。
挣扎了许久,这道题我们差不多纠结了两个小时。最后还是没招,看了题解。
又TM是ceil()的时候加干扰。。。实在是太鬼畜了。。。

/* written by tomriddly */#include <bits/stdc++.h>using namespace std;inline long long gcd(const long long &x, const long long &y){    return !y ? x : gcd(y, x % y);}/*struct Fenshu{    long long fenzi, fenmu;    inline Fenshu() {}    inline Fenshu(const long long &fenzi, const long long &fenmu):fenzi(fenzi), fenmu(fenmu) {}    inline friend bool operator <(const Fenshu &x, const Fenshu &y)    {        long long tongfen = gcd(x.fenmu, y.fenmu);        return x.fenzi * (x.fenmu / tongfen) < y.fenzi * (y.fenmu / tongfen);    }    inline friend Fenshu operator *(const Fenshu &x, const Fenshu &y)    {        long long fenzi = x.fenzi * y.fenzi, fenmu = x.fenmu * y.fenmu, tongfen = gcd(fenzi, fenmu);        return Fenshu(fenzi / tongfen, fenmu / tongfen);    }}*/typedef long double Fenshu;long double f[11][11];map<string, int> num;int n;int main(){    ios::sync_with_stdio(false);    int cas = 0;    while (cin >> n && n)    {        num.clear();        int n1, n2;        string name1, name2;        int cnt = 0;        memset(f, 0, sizeof(f));        for (int i = 1; i <= n; i++)        {            cin >> n1 >> name1 >> name2 >> n2 >> name2;            if (num.find(name1) == num.end())                num[name1] = ++cnt;            if (num.find(name2) == num.end())                num[name2] = ++cnt;            int u = num[name1], v = num[name2];            Fenshu v1 = (long double)n2 / n1, v2 = (long double)n1 / n2;            if (f[u][v] <= 1e-14 || v1 < f[u][v])                f[u][v] = v1;            if (f[v][u] <= 1e-14 || v2 < f[v][u])                f[v][u] = v2;        }        //cout << cnt << endl;        int need;        string needname;        for (int k = 1; k <= cnt; k++)            for (int i = 1; i <= cnt; i++)                for (int j = 1; j <= cnt; j++)                {                    if (f[i][k] <= 1e-14 || f[k][j] <= 1e-14)                        continue;                    Fenshu tmp = f[i][k] * f[k][j];                    if (f[i][j] <= 1e-14 || tmp < f[i][j])                        f[i][j] = tmp;                    //cout << tmp << endl;                }        cin >> need >> needname;        int t = num[needname];        double ans = DBL_MAX;        int ansi;        long long fff;        for (int i = 1; i <= cnt; i++)            if (i != t && f[i][t] >= 1e-14)            {                long long tmp = (long long)ceill((long double)need / f[i][t] - 1e-8);                if (tmp > 100000)                    continue;                double kui = fabs((long double)tmp / f[t][i] - need);                //cout << tmp << " " << i << ' ' << kui <<  endl;                if (ans > kui)                    ans = kui, ansi = i, fff = tmp;            }        cout << "Case " << (++cas) << ": ";        for (map<string, int>::iterator p = num.begin(); p != num.end(); p++)            if (p->second == ansi)            {                cout << fff << " " << p->first << endl;                break;            }    }}/*423 a = 17 b16 c = 29 e5 b = 14 e1 d = 7 f100 a*/

H题 Sofa, So Good

会了再补上。。


I题 Town Square

题意

只看懂了题意。。给四个圆,半径都是5。。求一个最小的正方形,与他们四个圆都相切。。
还不会,等会了再来补上。

0 0
原创粉丝点击