Looksery Cup 2015 A B D G H

来源:互联网 发布:怎么看淘宝卖家的信誉 编辑:程序博客网 时间:2024/04/28 08:08

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;}


0 0