Problem:
Problem B: Balloon Collecting "Balloons should be captured efficiently", the game designer says. He is designing an oldfashioned game with two dimensional graphics. In the game, balloons fall onto the ground one after another, and the player manipulates a robot vehicle on the ground to capture the balloons. The player can control the vehicle to move left or right, or simply stay. When one of the balloons reaches the ground, the vehicle and the balloon must reside at the same position, otherwise the balloon will burst and the game ends.   Figure B.1: Robot vehicle and falling balloons  The goal of the game is to store all the balloons into the house at the left end on the game field. The vehicle can carry at most three balloons at a time, but its speed changes according to the number of the carrying balloons. When the vehicle carries k balloons ( k = 0, 1, 2, 3), it takes k +1 units of time to move one unit distance. The player will get higher score when the total moving distance of the vehicle is shorter. Your mission is to help the game designer check game data consisting of a set of balloons. Given a landing position (as the distance from the house) and a landing time of each balloon, you must judge whether a player can capture all the balloons, and answer the minimum moving distance needed to capture and store all the balloons. The vehicle starts from the house. If the player cannot capture all the balloons, you must identify the first balloon that the player cannot capture. Input The input is a sequence of datasets. Each dataset is formatted as follows.  n  p 1  t 1 . . .  p n  t n  The first line contains an integer n, which represents the number of balloons (0 < n ≤ 40). Each of the following n lines contains two integers p i and t i (1 ≤ i ≤ n ) separated by a space. p i and t i represent the position and the time when the i -th balloon reaches the ground (0 < p i ≤ 100, 0 < t i ≤ 50000). You can assume t i < t j for i < j . The position of the house is 0, and the game starts from the time 0. The sizes of the vehicle, the house, and the balloons are small enough, and should be ignored. The vehicle needs 0 time for catching the balloons or storing them into the house. The vehicle can start moving immediately after these operations. The end of the input is indicated by a line containing a zero. Output For each dataset, output one word and one integer in a line separated by a space. No extra characters should occur in the output.  If the player can capture all the balloons, output "OK" and an integer that represents the minimum moving distance of the vehicle to capture and store all the balloons.  If it is impossible for the player to capture all the balloons, output "NG" and an integer k such that the k -th balloon in the dataset is the first balloon that the player cannot capture.  Sample Input 2
10 100
100 270
2
10 100
100 280
3
100 150
10 360
40 450
3
100 150
10 360
40 440
2
100 10
50 200
2
100 100
50 110
1
15 10
4
1 10
2 20
3 100
90 200
0 Output for the Sample Input OK 220
OK 200
OK 260
OK 280
NG 1
NG 2
NG 1
OK 188

Solution (Python):
inf = 1 << 28
while 1:
    n = int(raw_input())
    if n == 0: break
    pt = [map(int,raw_input().split()) for i in xrange(n)]
    p = [0]+[ele[0] for ele in pt]
    t = [0]+[ele[1] for ele in pt]

    dp = [[inf]*4 for i in xrange(n+1)]
    dp[0][0] = 0
    
    for i in xrange(1,n+1):
        for j in xrange(1,4):
            if (j+1)*p[i-1]+p[i] <= t[i]-t[i-1]:
                dp[i][1] = min(dp[i][1], dp[i-1][j]+p[i-1]+p[i])
            if abs(p[i-1]-p[i])*j <= t[i]-t[i-1]:
                dp[i][j] = min(dp[i][j], dp[i-1][j-1]+abs(p[i-1]-p[i]))
        if min(dp[i]) == inf:
            print "NG",i
            break
    else:
        for j in xrange(1,4):
            dp[-1][j] += p[-1]
        print "OK",min(dp[n])

Solution (Python):
INF = 10**9
while 1:
    n = input()
    if not n:
        break
    dp = [INF]*4
    dp[0] = 0
    pos = 0; time = 0
    k = -1
    ps = []; ts = []
    for i in xrange(n):
        p, t = map(int, raw_input().split())
        ps.append(p); ts.append(t)
    for i in xrange(n):
        p, t = ps[i], ts[i]
        d = abs(p - pos)
        can = False
        r = INF
        for j in xrange(3, -1, -1):
            if j<3:
                dp[j+1] = INF
            if dp[j] == INF:
                continue
            if j<3 and d*(j+1) <= t - time:
                can = True
                dp[j+1] = dp[j] + d
            if pos*(j+1) + p <= t - time:
                r = min(r, dp[j] + pos + p)
                can = True
        dp[1] = r
        dp[0] = INF
        if not can:
            k = i+1
            break
        pos, time = p, t
    if k!=-1:
        print "NG", k
        continue
    print "OK", (min(dp[1:]) + p)

Solution (Python):
INF = 10**9
while 1:
    n = input()
    if not n:
        break
    dp = [INF]*5
    dp[0] = 0
    pos = 0; time = 0
    k = -1
    ps = []; ts = []
    for i in xrange(n):
        p, t = map(int, raw_input().split())
        ps.append(p); ts.append(t)
    for i in xrange(n):
        p, t = ps[i], ts[i]
        d = abs(p - pos)
        can = False
        r = INF
        for j in xrange(3, -1 if i==0 else 0, -1):
            dp[j+1] = INF
            if dp[j] == INF:
                continue
            if j<3 and d*(j+1) <= t - time:
                can = True
                dp[j+1] = dp[j] + d
            if pos*(j+1) + p <= t - time:
                r = min(r, dp[j] + pos + p)
                can = True
        dp[1] = r
        if not can:
            k = i+1
            break
        pos, time = p, t
    if k!=-1:
        print "NG", k
    else:
        print "OK", (min(dp[1:]) + p)

Solution (Python):
import math,string,itertools,fractions,heapq,collections,re,array,bisect,sys,random,time,copy,functools

sys.setrecursionlimit(10**7)
inf = 10**20
eps = 1.0 / 10**10
mod = 10**9+7
dd = [(0,-1),(1,0),(0,1),(-1,0)]
ddn = [(0,-1),(1,-1),(1,0),(1,1),(0,1),(-1,-1),(-1,0),(-1,1)]

def LI(): return [int(x) for x in sys.stdin.readline().split()]
def LI_(): return [int(x)-1 for x in sys.stdin.readline().split()]
def LF(): return [float(x) for x in sys.stdin.readline().split()]
def LS(): return sys.stdin.readline().split()
def I(): return int(sys.stdin.readline())
def F(): return float(sys.stdin.readline())
def S(): return input()
def pf(s): return print(s, flush=True)


def main():
    rr = []

    while True:
        n = I()
        if n == 0:
            break
        a = [LI() for _ in range(n)]
        d = collections.defaultdict(lambda: inf)
        d[0] = 0
        cp = 0
        ct = 0
        r = inf
        for i in range(n):
            p,t = a[i]
            e = collections.defaultdict(lambda: inf)
            for k,ck in list(d.items()):
                if k < 3 and abs(cp-p) * (k+1) + ct <= t:
                    if e[k+1] > ck + abs(cp-p):
                        e[k+1] = ck + abs(cp-p)
                if cp * (k+1) + p + ct <= t:
                    if e[1] > ck + cp + p:
                        e[1] = ck + cp + p
            d = e
            if len(e) == 0:
                r = i + 1
                break
            cp = p
            ct = t

        if r < inf:
            rr.append('NG {}'.format(r))
        else:
            for k,ck in d.items():
                if r > ck + cp:
                    r = ck + cp
            rr.append('OK {}'.format(r))

    return '\n'.join(map(str,rr))


print(main())

Solution (Python):
inf = 10**9
while True:
    n = int(input())
    if n == 0:
        break
    b = [(0,0)]
    b.extend([tuple(map(int,input().split())) for i in range(n)])
    dp = [[inf]*4 for i in range(n+1)]
    dp[0][0] = 0
    for i in range(n):
        update = False
        for j in range(4):
            if dp[i][j] is inf:
                continue
            now = b[i][0]
            nxt = b[i+1][0]
            if j<=2 and b[i][1]+abs(nxt-now)*(j+1) <= b[i+1][1] and dp[i+1][j+1] > dp[i][j]+abs(nxt-now):
                dp[i+1][j+1] = dp[i][j]+abs(nxt-now)
                update = True
            if b[i][1]+now*(j+1)+nxt <= b[i+1][1] and dp[i+1][1] > dp[i][j]+nxt+now:
                dp[i+1][1] = dp[i][j]+nxt+now
                update = True
        if not update:
            print('NG',i+1)
            break
    if update:
        print('OK',min(dp[n])+b[n][0])

Solution (Python):

from collections import defaultdict,deque
from heapq import heappush, heappop
import sys
import math
import bisect
import random
def LI(): return [int(x) for x in sys.stdin.readline().split()]
def I(): return int(sys.stdin.readline())
def LS():return [list(x) for x in sys.stdin.readline().split()]
def S(): return list(sys.stdin.readline())[:-1]
def IR(n):
    return [I() for i in range(n)]
def LIR(n):
    return [LI() for i in range(n)]
def SR(n):
    return [S() for i in range(n)]
def LSR(n):
    return [LS() for i in range(n)]

sys.setrecursionlimit(1000000)
mod = 1000000007

def solve(n):
    b = LIR(n)
    if b[0][0] > b[0][1]:
        print("NG 1")
        return
    dp = [[float("inf") for j in range(4)] for i in range(n)]
    dp[0][1] = b[0][0]
    for i in range(n-1):
        ni = i+1
        x,t = b[i]
        for a in range(4):
            nx,nt = b[ni]
            if a < 3:
                na = a+1
                T = t+na*abs(nx-x)
                if T <= nt:
                    nd = dp[i][a]+abs(nx-x)
                    if nd < dp[ni][na]:
                        dp[ni][na] = nd
            na = 1
            T = t+(a+1)*x+nx
            if T > nt:
                continue
            nd = dp[i][a]+nx+x
            if nd < dp[ni][na]:
                dp[ni][na] = nd
    ans = float("inf")
    for i in range(4):
        ans = min(ans, dp[-1][i]+b[-1][0])
    if ans == float("inf"):
        for i in range(n):
            if min(dp[i]) == float("inf"):
                print("NG",i+1)
                return
    print("OK",ans)
    return


if __name__ == "__main__":
    while 1:
        n = I()
        if n == 0:
            break
        solve(n)

Solution (Python):

def do(b_num,step,now_p,item,t):
    global ans,p,memo
    if (b_num,step,now_p,item,t) in memo:
        return
    memo.add((b_num,step,now_p,item,t))
    if item==0 and b_num>=n:
        ans=min(ans,step)
        return
    
    if b_num<n and t+(item+1)*abs(balloons[b_num][0]-now_p)<=balloons[b_num][1] and item<=2:
        do(b_num+1,step+abs(balloons[b_num][0]-now_p),balloons[b_num][0],item+1,balloons[b_num][1])
    else:
        p=max(p,b_num)
    if now_p!=0:
        do(b_num,step+now_p,0,0,t+(item+1)*now_p)
 
while True:
    ans=99999999
    p=-1
    n=int(input())
    if n==0:
        break
    balloons=[]
    memo=set()
    for i in range(n):
        balloons.append(tuple(map(int,input().split())))
    do(0,0,0,0,0)
    if ans!=99999999:
        print('OK',ans)
    else:
        print('NG',p+1)