Digi Comp II: Difference between revisions

From programming_contest
Jump to navigation Jump to search
imported>Rubens
imported>Rubens
Line 74: Line 74:
<syntaxhighlight line lang="cpp">
<syntaxhighlight line lang="cpp">
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
 
#define INF 999999999


using namespace std;
using namespace std;


int tab[2005][15][25], nb[2005];
typedef struct node
bool visited[2005][15][25];
{
int n, d;
    long long int value;
    int leftInd, rightInd;
    int incoming;
    int v2, rp;
    char letter;
    bool visited;


int trying(int at, int rest, int x)
    void toggle() {
{
        if (letter == 'R')
    if (at == n)
            letter = 'L';
        return ((rest < 5) ? (rest) : (rest - 10));
         else
    if (x > d)
            letter = 'R';
         return -INF;
     }
    if (visited[at][rest][x])
} nodetype;
        return tab[at][rest][x];
     visited[at][rest][x] = true;
    return tab[at][rest][x] = max(trying(at+1, (rest+nb[at])%10, x), trying(at, 0, x+1) + ((rest < 5) ? (rest) : (rest - 10)));


}
nodetype node[500005];


int main()
int main()
{
{
     int s;
     priority_queue<int> sortednodes;
     int i, j, k;
     long long int n;
    int m, i;
 
    scanf (" %lld %d", &n, &m);
 
    for (i = 1; i <= m; i++) {
        scanf (" %c %d %d", &node[i].letter, &node[i].leftInd, &node[i].rightInd);
        node[node[i].leftInd].incoming++;
        node[node[i].rightInd].incoming++;
        node[i].value = 0;
    }


     while (scanf (" %d %d", &n, &d) != EOF)
     for (i = 1; i <= m; i++)
    {
         if (node[i].incoming == 0)
         memset(visited, 0, sizeof(visited));
            sortednodes.push(i);


         s = 0;
    node[1].value = n;
         for (i = 0; i < n; i++) {
 
             scanf (" %d", &nb[i]);
    while (!sortednodes.empty() && sortednodes.top() != 0) {
             s += nb[i];
         int at = sortednodes.top();
         sortednodes.pop();
 
        //printf("DB -- %d: v %lld\n", at, node[at].value);
 
        long long int leftv, rightv;
        leftv = rightv = node[at].value/2;
 
        if (node[at].value%2 != 0) {
             //printf("Hallo %c ", node[at].letter);
             if (node[at].letter == 'L')
                leftv++;
            else if (node[at].letter == 'R')
                rightv++;
            node[at].toggle();
            //printf("%c\n", node[at].letter);
         }
         }


         printf("%d\n", s-trying(0, 0, 0));
         node[node[at].leftInd ].value += leftv;
        node[node[at].rightInd].value += rightv;
 
        node[node[at].leftInd ].incoming--;
        node[node[at].rightInd].incoming--;
 
        if (node[node[at].leftInd ].incoming == 0)
            sortednodes.push(node[at].leftInd);
        if (node[node[at].rightInd].incoming == 0 && node[at].rightInd != node[at].leftInd)
            sortednodes.push(node[at].rightInd);
     }
     }
    for (i = 1; i <= m; i++)
        printf ("%c", node[i].letter);
    printf("\n");


     return 0;
     return 0;

Revision as of 00:43, 10 February 2015

Introduction

This problem asks you to simulate moving 10^18 items through a graph (500,000 nodes), where each node has a "next" state which changes whenever an item passes through

Solutions

Brute Force

Idea

Simulate passing every ball through the graph

Runtime

  • number of balls * number of nodes = 5 * 10^23

Simulate Nodes in order

Idea

  • There are no loops in the graph, so the balls will reach the nodes in topological sort order.
  • We only need to determine final node states, and node state only depends on number of balls that passed through the switch
  • Take nodes in topo-sort order
  • using the node start state, figure out how many balls will go to each successive state (somewhere around n/2)
  • Final node state is same if number is even (n%2==0) or different if odd (n%2==1)


Runtime

  • topological sort + simulation
  • n + n = 1,000,000

It is important to realize that our runtime CANNOT! include the number of balls....10^18 WAY too big

Gotchas

  • Must wait for ALL parent nodes to be processed before processing a given node (or else you might process it multiple (read: exponential) times)
  • Some parent nodes might never be reached (i.e. sources of the topological sort). Therefore we cannot just start with the given start nodes. we must start with ALL sources, whether they have any incoming marbles or not.

Code

Solution - Java

import java.util.*;
public class d {
Scanner in=new Scanner(System.in);
	public static void main(String[] args) {
		new d().go();
	}
	private void go() {
		long n=in.nextLong();
		int m=in.nextInt();
		long[][] d=new long[m+1][5];//state,L,R,incoming balls,incoming edges
		for(int i=1;i<m+1;i++){
			d[i][0]=in.next().equals("L")?0:1;
			d[i][1]=in.nextInt();
			d[i][2]=in.nextInt();
			d[(int) d[i][1]][4]++;
			d[(int) d[i][2]][4]++;
		}
		d[0][4]=Long.MAX_VALUE;
		d[1][3]=n;
		Queue<Integer> q=new LinkedList<Integer>();
		for(int i=0;i<m+1;i++)if(d[i][4]==0)q.offer(i);
		while(!q.isEmpty()){
			int on=q.poll();
			d[(int)d[on][(int)(d[on][0])+1]][3]+=d[on][3]/2+d[on][3]%2;//add to first
			d[(int)d[on][(int)((d[on][0]+1)%2)+1]][3]+=d[on][3]/2;//add to second
			if(d[on][3]%2==1)d[on][0]=(d[on][0]+1)%2;//flip switch
			d[(int) d[on][1]][4]--;//decrement incoming counts
			if(d[(int) d[on][1]][4]==0)q.offer((int) d[on][1]);
			d[(int) d[on][2]][4]--;
			if(d[(int) d[on][2]][4]==0)q.offer((int) d[on][2]);
		}
		StringBuilder sb=new StringBuilder("");
		for(int i=1;i<m+1;i++)sb.append(d[i][0]==0?"L":"R");
		System.out.println(sb.toString());
	}
}

Solution - C++

#include <stdio.h>
#include <queue>

using namespace std;

typedef struct node
{
    long long int value;
    int leftInd, rightInd;
    int incoming;
    int v2, rp;
    char letter;
    bool visited;

    void toggle() {
        if (letter == 'R')
            letter = 'L';
        else
            letter = 'R';
    }
} nodetype;

nodetype node[500005];

int main()
{
    priority_queue<int> sortednodes;
    long long int n;
    int m, i;

    scanf (" %lld %d", &n, &m);

    for (i = 1; i <= m; i++) {
        scanf (" %c %d %d", &node[i].letter, &node[i].leftInd, &node[i].rightInd);
        node[node[i].leftInd].incoming++;
        node[node[i].rightInd].incoming++;
        node[i].value = 0;
    }

    for (i = 1; i <= m; i++)
        if (node[i].incoming == 0)
            sortednodes.push(i);

    node[1].value = n;

    while (!sortednodes.empty() && sortednodes.top() != 0) {
        int at = sortednodes.top();
        sortednodes.pop();

        //printf("DB -- %d: v %lld\n", at, node[at].value);

        long long int leftv, rightv;
        leftv = rightv = node[at].value/2;

        if (node[at].value%2 != 0) {
            //printf("Hallo %c ", node[at].letter);
            if (node[at].letter == 'L')
                leftv++;
            else if (node[at].letter == 'R')
                rightv++;
            node[at].toggle();
            //printf("%c\n", node[at].letter);
        }

        node[node[at].leftInd ].value += leftv;
        node[node[at].rightInd].value += rightv;

        node[node[at].leftInd ].incoming--;
        node[node[at].rightInd].incoming--;

        if (node[node[at].leftInd ].incoming == 0)
            sortednodes.push(node[at].leftInd);
        if (node[node[at].rightInd].incoming == 0 && node[at].rightInd != node[at].leftInd)
            sortednodes.push(node[at].rightInd);
    }


    for (i = 1; i <= m; i++)
        printf ("%c", node[i].letter);
    printf("\n");

    return 0;
}