zoukankan      html  css  js  c++  java
  • LOJ 2977 「THUSCH 2017」巧克力

    LOJ 2977 「THUSCH 2017」巧克力

    神仙题QaQ

    做法是给每种颜色随机分配一个 $ 1 $ 到 $ k $ 的颜色,然后跑一次斯坦纳树,得到当前包含至少 $ k $ 种颜色的最小联通块。

    我们考虑什么时候我们可以随机到答案?如果答案的 $ k $ 颜色恰好本随机分配到了不同的颜色,那么跑出来的答案肯定就是正确的。所以说,一次随机的正确率大概是 $ frac{k!}{k^k} $ 大概是 $ 0.3% $ 。所以我们随机大概 200 次,正确率就远超 100 了。

    另外考虑中位数尽量小这个限制,我们二分这个中位数,考虑怎么 check ,当前我们的第一限制是块数,第二限制是拿到的大于中位数的尽可能少。由于我们要让 $ k $ 种联通,最多要选的块也不会超过 $ 5 imes (233 + 233) $ 不会超过 2000 多,实际上还肯定比这个小得多,保险起见(其实是方便)直接把大于中位数设置为 $ 10001 $ ,小于中位数 $ 9999 $ 。然后最后块数就是 $ lfloor frac{ans + 2500}{10000} floor $ ,这样就可以方便的验证了。

    #include "iostream"
    #include "algorithm"
    #include "cstring"
    #include "cstdio"
    #include "vector"
    #include "queue"
    using namespace std;
    int dirx[4] = { 0,0,-1,1 };
    int diry[4] = { 1,-1,0,0 };
    #define chkmn( a , b ) ( (a) > (b) ? ( (a) = (b) , 1 ) : 0 )
    #define MAXN 256
    int n , m , k , s;
    int c[MAXN][MAXN] , A[MAXN][MAXN] , w[MAXN][MAXN];
    int col[MAXN] , en , rc[MAXN];
    int dp[MAXN][MAXN][1<<5];
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define mp make_pair
    queue<pii> Q;
    int vis[MAXN][MAXN];
    void spfa( int s ) {
        while( !Q.empty() ) {
            int x = Q.front().fi , y = Q.front().se; Q.pop();
            vis[x][y] = 0;
            for( int d = 0 ; d < 4 ; ++ d ) {
                int X = x + dirx[d] , Y = y + diry[d];
                if( X < 1 || X > n || Y < 1 || Y > m || c[X][Y] == -1 ) continue;
                if( chkmn( dp[X][Y][s] , dp[x][y][s] + w[X][Y] ) && !vis[X][Y] )
                    Q.push( mp( X , Y ) ) , vis[X][Y] = 1;
            }
        }
    }
    int work(  ) {
        int ans = 0x3f3f3f3f;
        for( int t = 1 ; t <= 200 ; ++ t ) {
            random_shuffle( col + 1 , col + 1 + s );
            for( int i = 1 ; i <= s ; ++ i ) rc[col[i]] = i % k;
            for( int i = 1 ; i <= n ; ++ i )
                for( int j = 1 ; j <= m ; ++ j ) {
                    for (int st = 0; st < (1 << k); ++st) dp[i][j][st] = 0x3f3f3f3f;
                    if( ~c[i][j] ) dp[i][j][1<<rc[c[i][j]]] = w[i][j];
                }
            for( int st = 1 ; st < ( 1 << k ) ; ++ st ) {
                for( int i = 1 ; i <= n ; ++ i )
                    for( int j = 1 ; j <= m ; ++ j ) {
                        for( int t = ( st - 1 ) & st ; t ; t = ( t - 1 ) & st )
                            chkmn( dp[i][j][st] , dp[i][j][t] + dp[i][j][st ^ t] - w[i][j] ); // 转移
                        if( dp[i][j][st] < 1e9 ) Q.push( mp( i , j ) );
                    }
                spfa( st );
            }
            for( int i = 1 ; i <= n ; ++ i )
                for( int j = 1 ; j <= m ; ++ j ) ans = min( ans , dp[i][j][( 1 << k ) - 1]);
        }
        return ans;
    }
    int res;
    int main() {
        srand( 19260817 );
        int T;cin >> T;
        while( T --> 0 ) {
            cin >> n >> m >> k;
            for( int i = 1 ; i <= n ; ++ i ) for( int j = 1 ; j <= m ; ++ j )
                scanf("%d",&c[i][j]) , col[++ en] = c[i][j];
            for( int i = 1 ; i <= n ; ++ i ) for( int j = 1 ; j <= m ; ++ j )
                scanf("%d",&A[i][j]);
            sort( col + 1 , col + 1 + en );
            s = unique( col + 1 , col + 1 + en ) - col - 1;
            for( int i = 1 ; i <= n ; ++ i ) for( int j = 1 ; j <= m ; ++ j ) w[i][j] = 1;
            res = work( );
            if( res > 1e9 ) { puts("-1 -1"); continue; }
            int l = 0 , r = 1e6;
            while( l <= r ) {
                int mid = l + r >> 1;
                for( int i = 1 ; i <= n ; ++ i ) for( int j = 1 ; j <= m ; ++ j )
                    w[i][j] = ( A[i][j] <= mid ? 9999 : 10001 );
                int re = work( );
                if( re <= ( re + 2500 ) / 10000 * 10000 ) r = mid - 1;
                else l = mid + 1;
            }
            printf("%d %d
    ",res,l);
        }
    }
    
  • 相关阅读:
    2016级算法第四次上机-B ModricWang的序列问题
    2016级算法第四次上机-A.Bamboo 和人工zz
    2016级算法第三次上机-G.Winter is coming
    2016级算法第三次上机-F.ModricWang的导弹防御系统
    2016级算法第三次上机-E.ModricWang's Polygons
    2016级算法第三次上机-D.双十一的抉择
    2016级算法第三次上机-C.AlvinZH的奇幻猜想——三次方
    2016级算法第三次上机-B.Bamboo和巧克力工厂
    2016级算法第三次上机-A.Bamboo的小吃街
    Self-introduction 自我介绍
  • 原文地址:https://www.cnblogs.com/yijan/p/12319010.html
Copyright © 2011-2022 走看看