G3425's blog

By G3425, history, 4 months ago, In English

Switching On The Lights: USACO 2015, Silver. Problem 1.

Link: https://usaco.org/index.php?page=viewproblem2&cpid=570

My time (not the hit bo-en song): 46:34:69

Sidenote: Take everything I say with a LARGE grain of salt; my posts are meant to be an exercise to cement my ideas after coding a problem. I may very well be wrong.

Problem summary:

There is an N by N grid (2<=N<=100) representing rooms in a barn, numbered (1,1) to (N,N). Bessie starts at room (1,1), there are light switches that she can use to turn on the lights of other rooms. Bessie can only move through lit up rooms, find the max number of lit rooms Bessie can make.

Explanation:

Note: One cannot naively use DFS when solving this question, rooms continuously update and DFS does not allow one to check through all rooms. This leaves one with an answer which is under-counted, and unfortunately wrong.

Tricks I employed: - Resize all vectors to have walls, to prevent needing to check whether I go out of bounds - *Checking vis to see if a room is connected to the larger connected component - dx and dy to quickly check neighbors

This problem is like any other generic flood fill problem, the only thing that sets it apart is how the graph changes as she turns on the lights. As Bessie turns on more and more lights, there are new routes to explore that she could not go through initially. So, I used a BFS approach which allows floodfill to "go back" and check. To implement this, every time I encountered a room I checked if it was a neighbor to the main component, if it is I add it to the queue of rooms to check and add it to the main component itself. This way, I don't undercount.

Code:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define str string
#define vec vector
#define prq priority_queue
#define mprq(x) priority_queue<x, vec<x>, greater<x>>
#define FOR(i, a, b) for(int i = a; i < b; ++i)
#define print(x) for(auto i : x) {cout << i << " ";} cout << endl;
#define cinVec(x) for(auto& i : x) cin >> i;

int n, m;
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
vec<vec<bool>> lit;
vec<vec<bool>> vis;
vec<vec<vec<pair<int, int>>>> switches; //this is ... a monster.
int ans = 1;

void fast_io() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);
}

void flood(pair<int, int> pos){
    // BFS + flood
    queue<pair<int, int>> next; next.push(pos);
    vis[pos.first][pos.second] = true;
    while(!next.empty()){
        auto [x, y] = next.front(); next.pop();
        for(auto& i : switches[x][y]){
            auto [x_, y_] = i;
            if(!lit[x_][y_]){
                ++ans;
                lit[x_][y_] = true;
                FOR(j, 0, 4){
                    if(vis[x_+dx[j]][y_+dy[j]]){
                        next.push({x_, y_});
                        vis[x_][y_] = true;
                        break;
                    }
                }
            }
        }
        FOR(i, 0, 4){
            auto x_ = x+dx[i], y_ = y+dy[i];
            if(lit[x_][y_] && !vis[x_][y_]){
                vis[x_][y_] = true;
                next.push({x_, y_});
            }
        }
    }
}

int main(){
  //freopen("lightson.in", "r", stdin); freopen("lightson.out", "w", stdout);
  fast_io();
  //taking input
  cin >> n >> m;
  lit.resize(n+2, vec<bool>(n+2, false));
  vis.resize(n+2, vec<bool>(n+2, false));
  switches.resize(n+2, vec<vec<pair<int,int>>>(n+2));
  lit[1][1] = true;
  int a, b, x, y;
  FOR(i, 0, m){
    cin >> a >> b >> x >> y;
    switches[a][b].push_back({x, y});
  }

  //solving
  flood({1, 1});
  cout << ans << endl;
  return 0;
}

Afterthought:

Hello! I'm back with more ramblings, this time I know that there are actual people reading this so,,, yeah! I did use a hint on this problem because I wasn't entirely sure how to check through all the rooms; now I know I can use vis to track which items may be associated with the main component. Also know that as time goes on -- if I continue to post -- I will put significantly less effort into these (^-^).

PS. I'm not that great with programming, so if there is anything I can improve upon PLEASE let me know (that is, critique me all you want). PS.PS. HAPPY NEW YEAR (a few more hours for me)! Let's all improve this year, I for one hope to drag up my elo and not fail in USACO. - Quasistarsupernova.

Full text and comments »

  • Vote: I like it
  • -8
  • Vote: I do not like it

By G3425, history, 4 months ago, In English

Hello! I shall proceed to act schizophrenic for the entirety of this blog post, because I doubt anyone will be reading any of this. I suppose this is a great place to explain some USACO (silver) problems or CSF problems to an imaginary audience; apparently this helps cement ideas or something? Though, I first need to complete a USACO/CFS problem. So ... let me do that rq.

Problem Link: https://mirror.codeforces.com/problemset/problem/2181/B

Log:

  • 75s to read problem statement \n
  • 23:33, first sub; TLE on test 13. \n
  • 37:06, second sub; Happy new year! \n

Code:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define str string
#define vec vector
#define prq priority_queue
#define mprq(x) priority_queue<x, vec<x>, greater<x>>
#define FOR(i, a, b) for(ll i = a; i < b; ++i)
#define print(x) for(auto i : x) {cout << i << " ";} cout << endl;
#define cinVec(x) for(auto& i : x) cin >> i;

const ll MXN = 5e18 + 3, INF = 1e18 + 7;

void fast_io() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
}

int main() {
    fast_io();
    int t, x; cin >> t;
    while (t--) {
        ll n, m; cin >> n >> m;
        prq<ll> a, b;
        FOR(i, 0, n){
            cin >> x;
            a.push(x);
        }
        FOR(i, 0, m){
            cin >> x;
            b.push(x);
        }
        while (!a.empty() && !b.empty()) {
            ll topA = a.top(), topB = b.top();
            if (topA < topB) {
                b.pop();
                b.push(topB - topA);
            } else {
                b.pop();
            }
            if(a.empty() || b.empty()) break;
            topA = a.top(), topB = b.top();
            if(topA < topB){
                a.pop();
            } else {
                a.pop();
                a.push(topA - topB);
            }
        }
        if (b.empty()) cout << "Alice\n";
        else cout << "Bob\n";
    }
    return 0;
}

Cleaned code (more readable):

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define prq priority_queue
#define FOR(i, a, b) for(ll i = a; i < b; ++i)

void fast_io() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
}

int main() {
    fast_io();
    int t, x; cin >> t;
    while (t--) {
        ll n, m, tA, tB; cin >> n >> m;
        priority_queue<ll> a, b;
        FOR(i, 0, n){
            cin >> x;
            a.push(x);
        }
        FOR(i, 0, m){
            cin >> x;
            b.push(x);
        }
        while (!a.empty() && !b.empty()) {
            tA = a.top(), tB = b.top();
            b.pop();
            if (tA < tB) b.push(tB - tA);
            if(a.empty() || b.empty()) break;
            tA = a.top(), tB = b.top();
            a.pop();
            if(tA > tB) a.push(tA - tB);
        }
        if (b.empty()) cout << "Alice\n";
        else cout << "Bob\n";
    }
    return 0;
}

Alright, this is basically just a greedy priority queue question. I first did this with vectors, and then I realised that I should probably use priority queues instead, to not hit the TLE. Main concept: Basically, my solution was to be as greedy as possible. That is, the person who is currently having their move should try to reduce the other person's maximum number in their array. So, if it's Alice's turn she will compare her greatest number with Bob's greatest number. If it's larger, Bob will remove his number; otherwise, Bob will reduce his number. Priority queues were used to keep track of each of their largest numbers, as changes were made.

Example:

Alice: 30 30
Bob: 20 20 40

Alice: 30 30
Bob: 10 20 20

Alice: 10 30
Bob: 10 20 20

Alice: 10 30
Bob: 10 20

Alice: 10 10
Bob : 10 20

Alice: 10 10
Bob: 10 10

Alice: 10
Bob: 10 10

Alice: 10
Bob: 10

Alice:
BREAK.

Edit: got off my lazy bum and added an actual explanation instead of ridiculing the problem ;_; Also, what in the world, people are actually reading this (-///-). Sorry, didn't mean to be offensive,, I just got lazy

Alrighty, this has been your daily problem. I will (maybe) post here again if I feel like it. Also this was slightly a troll post because I didn't think people would actually see this, but here I am LMAO.

Full text and comments »

  • Vote: I like it
  • -4
  • Vote: I do not like it