Looksery Cup 2015 A B D G H

本文深入探讨了矩阵操作中计算face数量的方法,以及如何通过队列实现特定图的入度改变,同时涉及haar特征的变换、happy line的人际交换策略、退化矩阵的最小化等问题。文章详细解释了矩阵计算、图论应用、特征提取和优化算法的原理与实践。

A - Face Detection 矩阵里有多少个face

const int N = 55;
char a[N][N];

int main()
{
    int n, m;
    while( ~scanf("%d%d", &n, &m) ) {
        int ans = 0;
        for( int i = 1; i <= n; ++i )
            scanf("%s", a[i]+1);
        for( int i = 1; i < n; ++i ) {
            for( int j = 1; j < m; ++j ) {
                int c[30];
                memset( c, 0, sizeof( c ) );
                c[a[i][j] - 'a']++;
                c[a[i+1][j] - 'a']++;
                c[a[i][j+1] - 'a']++;
                c[a[i+1][j+1] - 'a']++;
                ans += c['f'-'a'] * c['a'-'a'] * c['c'-'a'] * c['e'-'a'];
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

B - Looksery Party 给出一张有向图,及一种可能的所有点的入度数组,问选出一些点来组成的新图,其里面的点的入度与给出的原来的入度数组完全不一样,求这样的方案。

首先可以选择那些原数组里面入度0的点,然后加入队列,每次从这些点出发到达另外一些点,如果那些点的入度和原数组一样,那就继续把这些点加入队列,直至队列为空

const int N = 120;

int a[N], b[N];
queue <int> q, ans;
char c[N][N];
int mat[N][N];
int n;

int main()
{
    while( ~scanf("%d", &n) ) {
        while( !q.empty() ) q.pop();
        while( !ans.empty() )   ans.pop();
        for( int i = 1; i <= n; ++i ) {
            scanf("%s", c[i]+1);
            for( int j = 1; j <= n; ++j ) {
                mat[i][j] = c[i][j] - '0';
            }
        }
        int x = 0, cnt = 0;
        for( int i = 1; i <= n; ++i ) {
            b[i] = 0;
            scanf("%d", &a[i]);
            x += (a[i] != 0);
            if( !a[i] ) {
                cnt++;
                ans.push(i);
                q.push(i);
            }
        }
        if( x == n ) {
            printf("0\n\n");
            continue;
        }
        while( !q.empty() ) {
            int now = q.front();
            q.pop();
            for( int i = 1; i <= n; ++i ) {
                if( mat[now][i] ) {
                    b[i]++;
                    if( b[i] == a[i] ) {
                        cnt++;
                        q.push(i);
                        ans.push(i);
                    }
                }
            }
        }
        printf("%d\n", cnt);
        while( !ans.empty() ) {
            printf("%d ", ans.front() );
            ans.pop();
        }
        puts("");
    }
    return 0;
}
D - Haar Features 题意:每次操作能让以包括左上角的矩阵里面的值都先乘上一个数,再加上一个数,问最少的次数变成给出的矩阵(w为1,b为0)

从右下角(n,m)开始遍历,每次遇到一个颜色不同的点(x,y),就翻转(1,1)到(x,y)的矩阵。时间是n^4(这么暴力都能过cf真乃神人也)

const int N = 105;
int n, m;
char a[N][N];
int s[N][N];
int t[N][N];

void flip( int x, int y, int z )
{
    for( int i = 1; i <= x; ++i ) {
        for( int j = 1; j <= y; ++j )
            t[i][j] += z;
    }
}

int main()
{
    while( ~scanf("%d%d", &n, &m) ) {
        for( int i = 1; i <= n; ++i )
            scanf("%s", a[i]+1);
        int ans = 0;
        memset( t, 0, sizeof( s ) );
        char x = a[1][1];
        for( int i = n; i >= 1; --i ) {
            for( int j = m; j >= 1; --j ) {
                if( a[i][j] == x )
                    s[i][j] = 1;
                else
                    s[i][j] = -1;
            }
        }
        for( int i = n; i >= 1; --i ) {
            for( int j = m; j >= 1; --j ) {
                if( s[i][j] != t[i][j] ) {
                    ans++;
                    flip( i, j, s[i][j] - t[i][j] );
                }
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

G - Happy Line 给出每个人的位置和现有的钱,每次可以和前面一个人交换位置,但是要给一块钱,没钱就不能继续交换了。最后求交换过后,每个人前面的人的钱都不能少于他本身。

可以将所有人的权值看成  他本身的现金+他到前排的距离。然后根据这个权值排序,排完后再去减去他现在的位置,最后扫一遍看看合法不合法即可

const int N = 200012;

int a[N];

int main()
{
    int n;
    while( ~scanf("%d", &n) ) {
        for( int i = 1; i <= n; ++i ) {
            scanf("%d", &a[i]);
            a[i] += i;
        }
        sort( a+1, a+1+n );
        bool check = 0;
        for( int i = 1; i <= n; ++i ) {
            a[i] -= i;
            if( a[i] < 0 || ( i >= 2 && a[i] < a[i-1] ) ) {
                check = 1;
                break;
            }
        }
        if( check )
            puts(":(");
        else {
            for( int i = 1; i <= n; ++i ) {
                printf("%d ", a[i]);
            }
            puts("");
        }
    }
    return 0;
}
H - Degenerate Matrix 给出一个现有矩阵 ,求一个退化矩阵B(即ad-bc = 0),且使|A-B|最小。

首先可以知道,|A-B|最小,则要保持|a-a'| = |b-b'| = |c-c'| = |d-d'|,设其为x。那么由a'd' = b'c',a'd'由a+x*d+x....a-x*d-x四种情况得到,同理b‘c’也是。a'd'和b'c'通过ad、bc的表达式解方程可以知道,当x为某值时,a+x*d+x....a-x*d-x这四种情况的值是差不多一样的,同理bc也是。根据a+x*d+x....a-x*d-x这四个表达式出来的最小值和bc这四个的最大值比较结果,二分x即可。详见代码

void f( double a, double b, double c, double d, double &minn, double &maxx )
{
    double q[5];
    int n = 0;
    q[++n] = a*c, q[++n] = a*d, q[++n] = b*c, q[++n] = b*d;
    sort( q+1, q+n+1 );
    minn = q[1], maxx = q[n];
}

int main()
{
    ll a, b, c, d;
    while( cin >> a >> b >> c >> d ) {
        double l = 0, r = (double) inf*10;
        for( int i = 1; i <= 300; ++i ) {
            double mid = 0.5 * ( l + r );
            double admin, admax, bcmin, bcmax;
            f( a-mid, a+mid, d-mid, d+mid, admin, admax );
            f( b-mid, b+mid, c-mid, c+mid, bcmin, bcmax );
            if( admin > bcmax || bcmin > admax )
                l = mid;
            else
                r = mid;
        }
        //printf("%.12f\n", (double) 0.5 * ( l+r ) );
        cout << fixed << setprecision(13) << (double) 0.5 * (l+r) << endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值