This would not work.
In order to run a gradient descent, you need to compute a gradient. So you need to have S0 requiring a gradient, same for S1 and all the states that will be input to your policy network.
Also, it’s cleaner to zero_grad the optimizer at the beginning of the loop in order to avoid “zero-ing” the gradient you are computing.
But before all, are you doing temporal-difference - based learning?  In that case you don’t update from C, but from the temporal difference error based on cost C:
optim.zero_grad()
S = Variable(S.data, requires_grad=True)
values = P(S)
A = greedy_choice(values) # that can be epsilon greedy or softmax
newS = Dynamics(S,A)
newC = Cost(newS)
TD = LossFunction(values, newC+P(newS)) 
TD.backward()
optim.step()
S = newS