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

训练感想

从今天开始,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;
            }
    }
}
/*
4
23 a = 17 b
16 c = 29 e
5 b = 14 e
1 d = 7 f
100 a
*/

H题 Sofa, So Good

会了再补上。。


I题 Town Square

题意

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值