Um objeto filho pode ser declarado como um objeto da classe Pai e a recíproca NÃO é verdadeira.
Mas o casting não é isso que você definiu aí.
O que você definiu foram alguns objeto do tipo A com referência a um objetos (filhos de A) do tipo B ou C.
ClassA p0 = new ClassA(); => variável de referência do tipo A criando um objeto do tipo A.
ClassB p1 = new ClassB(); => variável de referência do tipo B criando um objeto do tipo B.
ClassC p2 = new ClassC(); => variável de referência do tipo C criando um objeto do tipo C.
ClassA p3 = new ClassB(); => variável de referência do tipo A criando um objeto do tipo B. (Pode por causa do polimorfismo, B É-UM A).
ClassA p4 = new ClassC(); => variável de referência do tipo A criando um objeto do tipo C. (Pode por causa do polimorfismo, C É-UM A).
Diante dessas afirmações vamos analisar caso-a-caso:
A. está correto porque a variável de referência do tipo A pode mudar sua referência e passar a referenciar qualquer outro objeto onde o tipo da variável de referência seja do tipo A, B ou C.
B. está errada porque a variável de referência p1 é do tipo B e quer mudar sua referência para um objeto onde a variável que está referenciando-o é do tipo C.
C. está errado porque p2 é do tipo C e quer mudar sua referencia para um outro objeto onde quem está fazendo referência é do tipo A, até aí tudo bem porque C é um A, porém essa variável do tipo A pode estar referenciando tanto um objeto do tipo A, B ou C, só posso fazer essa referência se eu tiver certeza que o objeto que eu vou passar a referenciar agora seja do tipo C, logo necessita do CAST.
D. esta errado. cast incorreto pois B não É-UM C.
E. correto pelo motivo explicado no item C. Onde a variável de referência p1 é do tipo B e quer referenciar um outro objeto onde eu tenho certeza que é um B por conta do cast.
F. correto pelo mesmo motivo explicado no item F e C.
Acho que é isso, tentei ser o mais claro possível.