Devise a backtracking algorithm to allocate $p$ projects to $s$ students There are $p$ projects and $s$ students where $p \le s$. Multiple students can work on the same project but the same student cannot work on multiple projects. All projects must be allocated and all students must have a project. I need to compute and display all possible ways of allocating projects to students under these constraints. Here's an example:

Input: 

3 students, 2 projects

Output:

   P1      P2
   {1}     {2, 3}
   {2}     {1, 3}
   {3}     {1, 2}
   {1, 2}  {3}
   {1, 3}  {2}
   {2, 3}  {1}


In my attempts, I've thought about this as being related to the problem of partitioning the set of students into non empty subsets and then ignoring those partitions which have unacceptable length. i.e. for my example generate: 

{{1}, {2}, {3}}
{{1}, {2, 3}}
{{2}, {1, 3}}
{{3}, {1, 2}}
{{1, 2, 3}}


and ignore the first and last as well as double count the three in the middle as they can be arranged in a two ways (order matters for this problem). I'm not sure however how I would go about generating and filtering these subsets and even whether this is a decent solution for any p or s values.
I didn't get what you're exatly asking for? Backtracking is the solution. Are you looking for an actual implementation or an explanation of backtracking? Or a  better  performing approach in terms of runtime.

Here my pseudo code how I would generate all matching solutions.

state = [];  //array representing the current state, assigns students to projects

S = [..];    //array containing the students
P = [..];    //array with students
func assign(level) {
  if(level == S.length) {
    if is_valid_state() //ensure each project has at least one student
      output(state);
  }
  for(i = 0; i &lt; P.length; i++) {
    state[level] = i;
    assign(level+1);
  }
}

level(0)


Can of course  be optimized by moving the final condition atop, but this would be my first thought of how to solving this the least efficient way (in terms of performance).