An algorithm for solving the protein docking problem is presented. Many tentative dockings are first generated by requiring a hole on the surface of one protein to match a knob on the surface of the other. All the tentative dockings are then applied. The initial configurations thus generated are further optimized. The optimization is facilitated by giving a discrete representation to the protein interior and a double-layer discrete representation to the protein surface. The algorithm presented correctly predicts the association of trypsin with its inhibitor as well as that of the alpha and beta subunits in hemoglobin.