First thing you need to do is deal with the "most recent exam" condition.  
The following gets the most recent exam for each student by subject...
SELECT
  [Result].StudentID,
  [Exam].SubjectID,
  MAX([Exam].id) AS ExamID
FROM
  Result
     INNER JOIN
  Exam
     ON [Exam].id = [Result].ExamID
GROUP BY
  [Result].StudentID,
  [Exam].SubjectID
You then need to get the grade for each exam, and apply your restrictions...
SELECT
  [Recent].StudentID
FROM
(
  SELECT
    [Result].StudentID,
    [Exam].SubjectID,
    MAX([Exam].id) AS ExamID
  FROM
    Result
       INNER JOIN
    Exam
       ON [Exam].id = [Result].ExamID
  GROUP BY
    [Result].StudentID,
    [Exam].SubjectID
)
  AS [Recent]
INNER JOIN
  Result
    ON  [Result].StudentID = [Recent].StudentID
    AND [Result].ExamID    = [Recent].ExamID
GROUP BY
  [Recent].StudentID
HAVING
  MIN(      
    CASE [Exam].SubjectID
       WHEN 'Maths'   THEN CASE WHEN GradeID = 'A' THEN 1 ELSE 0 END
       WHEN 'English' THEN CASE WHEN GradeID = 'B' THEN 1 ELSE 0 END
       ELSE 1
    END
  )
  = 1
If you know that you only want MATHS and ENGLISH this can be sped up by putting a WHERE clause in the sub query for [Recent]...
  WHERE
    [Exam].Subject IN ('Maths', 'English')
EDIT:
The "MIN(CASE) = 1" part of the query works as follows...
- If the subject is Maths, and they get an A, then 1.  Else 0.
- If the subject is English, and they get a B, then 1.  Else 0.
- If the subject is anything else, then 1.  
If any of these returns 0, ignore that student.
Thus, if a student has Maths:A, English:B, Geography:A, the Geography WON'T cause a 0 and so won't cause the student to be ignored, no matter what their geography grade.
Thinking about it more now though, if they don't have a grade in Maths and/or English, they could still pass this check.  If you want to exclude students who have not taken the Maths and/or English tests, use this HAVING clause instead...
  SUM(      
    CASE [Exam].SubjectID
       WHEN 'Maths'   THEN CASE WHEN GradeID = 'A' THEN 1 ELSE 0 END
       WHEN 'English' THEN CASE WHEN GradeID = 'B' THEN 1 ELSE 0 END
       ELSE 0
    END
  )
  = 2
The ELSE 0 ensures other subjects are ignored, and the SUM() = 2 ensures both conditions are matched.
EDIT:
To put the requirements in a table (and speed everything up)...
DECLARE @requirements TABLE (
  SubjectID    NVARCHAR(32),
  GradeID      NCHAR(1)
  )
INSERT INTO @requirements VALUES (N'Maths',   N'A')
INSERT INTO @requirements VALUES (N'English', N'B')
SELECT
  [Recent].StudentID
FROM
(
  SELECT
    [Result].StudentID     AS [StudentID],
    [Exam].SubjectID       AS [SubjectID],
    MAX([Exam].id)         AS [ExamID],
    [Requirements].GradeID AS [RequiredGrade]
  FROM
    Exam
  INNER JOIN
    @requirements [Requirements]
      ON [Requirements].SubjectID = [Exam].SubjectID
  INNER JOIN   
    Result
      ON [Exam].id = [Result].ExamID
  GROUP BY
    [Result].StudentID,
    [Exam].SubjectID,
    [Requirements].GradeID AS RequiredGrade
)
  AS [StudentExam]
INNER JOIN
  Result
    ON  [Result].StudentID = [StudentExam].StudentID
    AND [Result].ExamID    = [StudentExam].ExamID
    AND [Result].GradeID   = [StudentExam].RequiredGrade
GROUP BY
  [Recent].StudentID
HAVING
  COUNT(*) = (SELECT COUNT(*) FROM @requirements)
As mentioned in another post, if you can get an ExamDate in there, that would be more reliable than the ExamID column.  It should also be said, provided you have enough control over the database, you should be able to prevent the Identity value doing anything other than going forwards.