Submission #1137114

#TimeUsernameProblemLanguageResultExecution timeMemory
1137114Zbyszek99Game (eJOI20_game)C++20
0 / 100
0 ms328 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define ll long long
#define ld long double
#define ull unsigned long long
#define ff first
#define ss second
#define pii pair<int,int>
#define pll pair<long long, long long>
#define vi vector<int>
#define vl vector<long long>
#define pb push_back
#define rep(i, b) for(int i = 0; i < (b); ++i)
#define rep2(i,a,b) for(int i = a; i <= (b); ++i)
#define rep3(i,a,b,c) for(int i = a; i <= (b); i+=c)
#define count_bits(x) __builtin_popcountll((x))
#define all(x) (x).begin(),(x).end()
#define siz(x) (int)(x).size()
#define forall(it,x) for(auto& it:(x))
using namespace __gnu_pbds;
using namespace std;
typedef tree<int, null_type, less<int>, rb_tree_tag,tree_order_statistics_node_update> ordered_set;
//mt19937 mt;void random_start(){mt.seed(chrono::time_point_cast<chrono::milliseconds>(chrono::high_resolution_clock::now()).time_since_epoch().count());}
//ll los(ll a, ll b) {return a + (mt() % (b-a+1));}
const int INF = 1e9+50;
const ll INF_L = 1e18+40;
const ll MOD = 1e9+7;

int dp[445][445][2][2];
int rep_[445];
int siz_[445];
bool is_path[445];
int sides[445];

int fint(int v)
{
    if(rep_[v] == v) return v;
    rep_[v] = fint(rep_[v]);
    return rep_[v];
}

void onion(int a, int b)
{
    a = fint(a);
    b = fint(b);
    if(a == b) return;
    siz_[b] += siz_[a];
    rep_[a] = b;
    is_path[b] = is_path[b] || is_path[a];
}

int main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //random_start();
    int n,m;
    cin >> n >> m;
    rep(i,n*m)
    {
        rep_[i] = i;
        siz_[i] = 1;
    }
    rep(i,n+1)
    {
        rep(j,m)
        {
            char z;
            cin >> z;
            if(z == '1')
            {
                if(i!=n)
                {
                    sides[i*m+j]++;
                }
                if(i!=0)
                {
                    sides[(i-1)*m+j]++;
                }
            }
            else
            {
                if(i > 0 && i < n)
                {
                    onion(i*m+j,(i-1)*m+j);
                }
                if(i == 0)
                {
                    is_path[fint(i*m+j)] = 1;
                }
                if(i == n)
                {
                    is_path[fint((i-1)*m+j)] = 1;
                }
            }
        }
    }
    rep(i,n)
    {
        rep(j,m+1)
        {
            char z;
            cin >> z;
            if(z == '1')
            {
                if(j!=n)
                {
                    sides[i*m+j]++;
                }
                if(j!=0)
                {
                    sides[i*m+j-1]++;
                }
            }
            else
            {
                if(j > 0 && j < m)
                {
                    onion(i*m+j,i*m+j-1);
                }
                if(j == 0)
                {
                    is_path[fint(i*m+j)] = 1;
                }
                if(j == m)
                {
                    is_path[fint(i*m+j-1)] = 1;
                }
            }
        }
    }
    vector<int> paths;
    vector<int> cycles;
    rep(i,n*m)
    {
        if(fint(i) == i && sides[i] != 4)
        {
            if(is_path[i])
            {
                paths.pb(siz_[i]);
            }
            else
            {
                cycles.pb(siz_[i]);
            }
        }
    }
    sort(all(paths));
    sort(all(cycles));
    for(int p = siz(paths); p >= 0; p--)
    {
        //cout << comps[i] << " comps\n";
        for(int c = siz(cycles); c >= 0; c--)
        {
            if(p == siz(paths) && c == siz(cycles))
            {
                continue;
            }
            dp[p][c][0][0] = -1e5;
            dp[p][c][0][1] = -1e5;
            dp[p][c][1][0] = 1e5;
            dp[p][c][1][1] = 1e5;
            
            if(p < siz(paths))
            {
                // 0 0
                if(p == siz(paths)-1 && c == siz(cycles)) dp[p][c][0][0] = paths[p];
                if(p+1 < siz(paths))
                {
                    dp[p][c][0][0] = max(dp[p][c][0][0],dp[p+1][c][1][0] + paths[p]);
                }
                if(c < siz(cycles))
                {
                    dp[p][c][0][0] = max(dp[p][c][0][0],dp[p+1][c][1][1] + paths[p]);
                }
                if(paths[p] > 2)
                {
                    int w2 = 1e5;
                    if(p + 1 < siz(paths))
                    {
                        w2 = min(w2,dp[p+1][c][0][0]);
                    }
                    if(c < siz(cycles))
                    {
                        w2 = min(w2,dp[p+1][c][0][1]);
                    }
                    if(w2 != 1e5)
                    dp[p][c][0][0] = max(dp[p][c][0][0],w2 + paths[p] - 4);
                }
                //1 0
                if(p == siz(paths)-1 && c == siz(cycles)) dp[p][c][1][0] = -paths[p];
                if(p + 1 < siz(paths))
                {
                    dp[p][c][1][0] = min(dp[p][c][1][0],dp[p+1][c][0][0] - paths[p]);
                }
                if(c < siz(cycles))
                {
                    dp[p][c][1][0] = min(dp[p][c][1][0],dp[p+1][c][0][1] - paths[p]);
                }
                if(paths[p] > 2)
                {
                    int w2 = -1e5;
                    if(p + 1 < siz(paths))
                    {
                        w2 = max(w2,dp[p+1][c][1][0]);
                    }
                    if(c < siz(cycles))
                    {
                        w2 = max(w2,dp[p+1][c][1][1]);
                    }
                    if(w2 != -1e5)
                    dp[p][c][1][0] = min(dp[p][c][1][0],w2 - paths[p] + 4);
                }
            }
            if(c < siz(cycles))
            {
                // 0 1
                if(c == siz(cycles)-1 && p == siz(paths)) dp[p][c][0][1] = cycles[c];
                if(p < siz(paths))
                {
                    dp[p][c][0][1] = max(dp[p][c][0][1],dp[p][c+1][1][0]+cycles[c]);
                }
                if(c + 1 < siz(cycles))
                {
                    dp[p][c][0][1] = max(dp[p][c][0][1],dp[p][c+1][1][1]+cycles[c]);
                }
                int w2 = 2e5;
                if(p < siz(paths))
                {
                    w2 = min(w2,dp[p][c+1][0][0]);
                }
                if(c + 1 < siz(cycles))
                {
                    w2 = min(w2,dp[p][c+1][0][1]);
                }
                if(w2 != 2e5)
                dp[p][c][0][1] = max(dp[p][c][0][1],w2 + cycles[c] - 8);
                // 1 1
                if(c == siz(cycles)-1 && p == siz(paths)) dp[p][c][1][1] = -cycles[c];
                if(p < siz(paths))
                {
                    dp[p][c][1][1] = min(dp[p][c][1][1],dp[p][c+1][0][0]-cycles[c]);
                }
                if(c + 1 < siz(cycles))
                {
                    dp[p][c][1][1] = min(dp[p][c][1][1],dp[p][c+1][0][1]-cycles[c]);
                }
                w2 = -2e5;
                if(p < siz(paths))
                {
                    w2 = max(w2,dp[p][c+1][1][0]);
                }
                if(c + 1 < siz(cycles))
                {
                    w2 = max(w2,dp[p][c+1][1][1]);
                }
                if(w2 != -2e5)
                dp[p][c][1][1] = min(dp[p][c][1][1],w2 - cycles[c] + 8);
            }
         //   cout << "paths: " << p << " cycles: " << c << "\n";
         //   cout << dp[p][c][0][0] << " 00\n";
         //   cout << dp[p][c][0][1] << " 01\n";
         //   cout << dp[p][c][1][0] << " 10\n";
        //    cout << dp[p][c][1][1] << " 11\n\n";   
        }
    }
    //cout << siz(paths) << " " << siz(cycles) << " " << cycles[0] << " sizy\n";
    if(siz(paths) == 0 && siz(cycles) == 0)
    {
        cout << 0;
        return 0;
    }
    cout << max((siz(paths) != 0 ? dp[0][0][1][0] : (int)-2e5),(siz(cycles) != 0 ? dp[0][0][1][1]: (int)-2e5)) << "\n";
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...