Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include<bits/stdc++.h>
- #include <ext/pb_ds/assoc_container.hpp>
- //pragmas
- #pragma GCC optimize("03")
- #pragma GCC target("avx,avx2,fma")
- //#pragma GCC optimization("01, 02, 03, 0fast, unroll-loops") //Retard mode
- //#pragma GCC optimize("Ofast,unroll-loops,omit-frame-pointer,inline") //Optimization flags
- //#pragma GCC option("arch=native,tune=native,no-zero-upper") //Enable AVX
- //types
- #define fastio() ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
- #define ll long long
- #define TYPE long long
- #define ppair pair<TYPE, TYPE>
- #define vecvec(a, i, j, x) vector<vector<TYPE>> a (i, vector<TYPE> (j, x))
- #define vecvecvec(a, i, j, k, x) vector<vector<vector<TYPE>>> a (i + 1, vector<vector<TYPE>>(j + 1, vector<TYPE>(k + 1, x)))
- using namespace std;
- using namespace __gnu_pbds;
- //random stuff
- #define all(a) a.begin(),a.end()
- #define endl "\n"
- #define pb push_back
- #define mp make_pair
- #define sz(x) (long long int)x.size()
- #define F first
- #define S second
- #define sp " "
- const ll inf = 0x3f3f3f3f, INF = 1e18;
- const int MOD = 1e9 + 7;
- const ll BIG_MOD = 489133282872437279; //use to decrease hash collision probability
- typedef tree<long long int, null_type, less<long long int>, rb_tree_tag, tree_order_statistics_node_update> indexed_set; //for multiset, use less_equal and erase x in multiset a -> a.erase(a.find_by_order(a.order_of_key(x)))
- struct custom_hash {
- static uint64_t splitmix64(uint64_t x) {
- x += 0x9e3779b97f4a7c15;
- x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
- x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
- return x ^ (x >> 31);
- }
- size_t operator()(uint64_t x) const {
- static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
- return splitmix64(x + FIXED_RANDOM);
- }
- };
- #define safe_map unordered_map<long long, int, custom_hash>
- #define hashmap gp_hash_table<int, int, custom_hash>
- //debug
- void __print(int x) {cerr << x;}
- void __print(long x) {cerr << x;}
- void __print(long long x) {cerr << x;}
- void __print(unsigned x) {cerr << x;}
- void __print(unsigned long x) {cerr << x;}
- void __print(unsigned long long x) {cerr << x;}
- void __print(float x) {cerr << x;}
- void __print(double x) {cerr << x;}
- void __print(long double x) {cerr << x;}
- void __print(char x) {cerr << '\'' << x << '\'';}
- void __print(const char *x) {cerr << '\"' << x << '\"';}
- void __print(const string &x) {cerr << '\"' << x << '\"';}
- void __print(bool x) {cerr << (x ? "true" : "false");}
- template<typename T, typename V>
- void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ','; __print(x.second); cerr << '}';}
- template<typename T>
- void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), __print(i); cerr << "}";}
- void _print() {cerr << "]\n";}
- template <typename T, typename... V>
- void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
- #ifndef ONLINE_JUDGE
- #define debug(x...) {cerr << "[" << #x << "] = ["; _print(x);}
- #define reach cerr<<"reached"<<endl
- #else
- #define debug(x...)
- #define reach
- #endif
- /*---------------------------------------------------------------------------------------------------------------------------*/
- ll gcd(ll a, ll b) {if (b > a) {return gcd(b, a);} if (b == 0) {return a;} return gcd(b, a % b);}
- ll expo(ll a, ll b, ll mod) {ll res = 1; while (b > 0) {if (b & 1)res = (res * a) % mod; a = (a * a) % mod; b = b >> 1;} return res;}
- void extendgcd(ll a, ll b, ll*v) {if (b == 0) {v[0] = 1; v[1] = 0; v[2] = a; return ;} extendgcd(b, a % b, v); ll x = v[1]; v[1] = v[0] - v[1] * (a / b); v[0] = x; return;} //pass an arry of size1 3
- ll mminv(ll a, ll b) {ll arr[3]; extendgcd(a, b, arr); return arr[0];} //for non prime b
- ll mminvprime(ll a, ll b) {return expo(a, b - 2, b);}
- bool revsort(ll a, ll b) {return a > b;}
- void swap(int &x, int &y) {int temp = x; x = y; y = temp;}
- ll combination(ll n, ll r, ll m, ll *fact, ll *ifact) {ll val1 = fact[n]; ll val2 = ifact[n - r]; ll val3 = ifact[r]; return (((val1 * val2) % m) * val3) % m;}
- void google(int t) {cout << "Case #" << t << ": ";}
- vector<ll> sieve(int n) {int*arr = new int[n + 1](); vector<ll> vect; for (ll i = 2; i <= n; i++)if (arr[i] == 0) {vect.push_back(i); for (ll j = 2 * i; j <= n; j += i)arr[j] = 1;} return vect;}
- ll mod_add(ll a, ll b, ll m = MOD) {a = a % m; b = b % m; return (((a + b) % m) + m) % m;}
- ll mod_mul(ll a, ll b, ll m = MOD) {a = a % m; b = b % m; return (((a * b) % m) + m) % m;}
- ll mod_sub(ll a, ll b, ll m = MOD) {a = a % m; b = b % m; return (((a - b) % m) + m) % m;}
- ll mod_div(ll a, ll b, ll m = MOD) {a = a % m; b = b % m; return (mod_mul(a, mminvprime(b, m), m) + m) % m;} //only for prime m
- ll phin(ll n) {ll number = n; if (n % 2 == 0) {number /= 2; while (n % 2 == 0) n /= 2;} for (ll i = 3; i <= sqrt(n); i += 2) {if (n % i == 0) {while (n % i == 0)n /= i; number = (number / i * (i - 1));}} if (n > 1)number = (number / n * (n - 1)) ; return number;} //O(sqrt(N))
- void precision(int a) {cout << setprecision(a) << fixed;}
- ll ceil_div(ll x, ll y){return (x + y - 1) / y;}
- unsigned long long power(unsigned long long x,ll y, ll p){unsigned long long res = 1;x = x % p; while (y > 0){if (y & 1)res = (res * x) % p;y = y >> 1;x = (x * x) % p;}return res;}
- unsigned long long modInverse(unsigned long long n,int p){return power(n, p - 2, p);}
- ll nCr(ll n,ll r, ll p){if (n < r)return 0;if (r == 0)return 1;unsigned long long fac[n + 1];fac[0] = 1;for (int i = 1; i <= n; i++)fac[i] = (fac[i - 1] * i) % p;return (fac[n] * modInverse(fac[r], p) % p* modInverse(fac[n - r], p) % p)% p;}
- ll accumulate(const vector<long long int> &nums){ll sum = 0; for(auto x : nums) sum += x; return sum;}
- ll tmax(ll a, ll b, ll c = 0, ll d = -INF, ll e = -INF, ll f = -INF){return max(a, max(b, max(c, max(d, max(e, f)))));}
- int log2_floor(unsigned long long i) {return i ? __builtin_clzll(1) - __builtin_clzll(i) : -1;}
- string bin(ll n){return bitset<32>(n).to_string();}
- /*--------------------------------------------------------------------------------------------------------------------------*/
- #define int int64_t
- const int MAXN = 325;
- int64_t a[MAXN][MAXN];
- bool vis[MAXN][MAXN];
- int64_t sd[MAXN][MAXN], ed[MAXN][MAXN];
- int64_t dp[5][MAXN][MAXN];
- void clear_vis(int r, int c)
- {
- for(int i = 1; i <= r; i ++)
- for(int j = 1; j <= c; j ++)
- vis[i][j] = false;
- }
- //code starts
- void main_()
- {
- #ifndef ONLINE_JUDGE
- freopen("input.txt", "r", stdin);
- freopen("output.txt", "w", stdout);
- freopen("output.txt", "w", stderr);
- #endif
- int tt;
- cin >> tt;
- for(int t = 1; t <= tt; t ++)
- {
- int r, c;
- cin >> r >> c;
- for(int i = 0; i <= r + 3; i ++)
- for(int j = 0; j <= c + 3; j ++)
- sd[i][j] = ed[i][j] = 0, dp[1][i][j] = dp[2][i][j] = dp[3][i][j] = dp[4][i][j] = INF;
- for(int i = 1; i <= r; i ++)
- for(int j = 1; j <= c; j ++)
- cin >> a[i][j];
- for(int i = 0; i < r + 3; i ++) vis[i][0] = vis[i][c + 1] = true;
- for(int j = 0; j < c + 3; j ++) vis[0][j] = vis[r + 1][j] = true;
- clear_vis(r, c);
- function<void(int, int)> fcalc = [&](int x, int y)
- {
- if(!vis[x - 1][y] or !vis[x][y - 1]) return;
- vis[x][y] = true;
- sd[x][y] = a[x][y] + max((int64_t)0, max(sd[x - 1][y], sd[x][y - 1]));
- if(x != r) fcalc(x + 1, y);
- if(y != c) fcalc(x, y + 1);
- };
- fcalc(1, 1);
- clear_vis(r, c);
- function<void(int, int)> rcalc = [&](int x, int y)
- {
- if(!vis[x + 1][y] or !vis[x][y + 1]) return;
- vis[x][y] = true;
- ed[x][y] = a[x][y] + max((int64_t)0, max(ed[x + 1][y], ed[x][y + 1]));
- if(x != 1) rcalc(x - 1, y);
- if(y != 1) rcalc(x, y - 1);
- };
- rcalc(r, c);
- //now the main dp
- clear_vis(r, c);
- function<void(int, int)> calc = [&](int x, int y)
- {
- if(!vis[x - 1][y] or !vis[x][y + 1]) return;
- vis[x][y] = true;
- //last cell was to the right (current is 1 or 3, last state was 1 or 4)
- // if(y != c)
- // {
- // calculate for current type 1
- dp[1][x][y] = min(dp[1][x][y], min(
- max(dp[1][x][y + 1], sd[x - 1][y] + ed[x + 1][y]),
- max(dp[4][x][y + 1], sd[x - 1][y] + ed[x + 1][y])
- ));
- // calculate for current type 3
- dp[3][x][y] = min(dp[3][x][y], min(
- max(dp[1][x][y + 1], max(sd[x - 1][y], sd[x][y - 1]) + ed[x + 1][y + 1]),
- max(dp[4][x][y + 1], max(sd[x - 1][y], sd[x][y - 1]) + max(ed[x + 1][y + 1], ed[x][min(c + 1, y + 2)]))
- ));
- // }
- // last cell was above (current is 2 or 4, last state was 2 or 3)
- // if(x != 1)
- // {
- // calculate for current type 2
- dp[2][x][y] = min(dp[2][x][y], min(
- max(dp[2][x - 1][y], sd[x][y - 1] + ed[x][y + 1]),
- max(dp[3][x - 1][y], sd[x][y - 1] + ed[x][y + 1])
- ));
- // calculate for current type 4
- dp[4][x][y] = min(dp[4][x][y], min(
- max(dp[2][x - 1][y], sd[x - 1][y - 1] + max(ed[x + 1][y], ed[x][y + 1])),
- max(dp[3][x - 1][y], max(sd[max((int)0, x - 2)][y], sd[x - 1][y - 1]) + max(ed[x + 1][y], ed[x][y + 1]))
- ));
- // }
- if(x != r) calc(x + 1, y);
- if(y != 1) calc(x, y - 1);
- };
- for(int type = 1; type <= 4; type ++)
- dp[type][1][c] = 0;
- calc(1, c);
- int64_t ans = INF;
- for(int type = 1; type <= 4; type ++)
- ans = min(ans, dp[type][r][1]);
- cout << "Case #" << t << ": " << ans << endl;
- }
- }
- /*
- 1: x x x
- 2: x
- x
- x
- 3: x x
- x
- 4: x
- x x
- */
- static void run_with_stack_size(void (*func)(void), size_t stsize)
- {
- char *stack, *send;
- stack = (char *)malloc(stsize);
- send = stack + stsize - 16;
- send = (char *)((uintptr_t)send / 16 * 16);
- asm volatile(
- "mov %%rsp, (%0)\n"
- "mov %0, %%rsp\n"
- :
- : "r"(send));
- func();
- asm volatile("mov (%0), %%rsp\n" : : "r"(send));
- free(stack);
- }
- int32_t main()
- {
- run_with_stack_size(main_, 1024 * 1024 * 1024); // run with a 1 GiB stack
- return 0;
- }
Add Comment
Please, Sign In to add comment