SPOJ Problem 423: Assignmentsに問題があります。
この問題では、n 個の固有のトピックを n 個の固有の生徒に割り当てることができる割り当ての数を数えて、各生徒が好きなトピックを 1 つだけ取得できるようにすることを求めています。入力を と呼ばれるリストのリストに解析する方法を思いつきましたpreferences
。各内部リストは、1 人の生徒が好きなトピック (0 から n-1 までの整数で示される) のリストです。
入力の例:
1 1 1
1 1 1
1 1 1
私は得る[[0, 1, 2], [0, 1, 2], [0, 1, 2]]
。
そして入力のために:
1 0 0 1 0 0 0 0 0 1 1
1 1 1 1 1 0 1 0 1 0 0
1 0 0 1 0 0 1 1 0 1 0
1 0 1 1 1 0 1 1 0 1 1
0 1 1 1 0 1 0 0 1 1 1
1 1 1 0 0 1 0 0 0 0 0
0 0 0 0 1 0 1 0 0 0 1
1 0 1 1 0 0 0 0 0 0 1
0 0 1 0 1 1 0 0 0 1 1
1 1 1 0 0 0 1 0 1 0 1
1 0 0 0 1 1 1 1 0 0 0
リストを取得します[[0, 3, 9, 10], [0, 1, 2, 3, 4, 6, 8], [0, 3, 6, 7, 9], [0, 2, 3, 4, 6, 7, 9, 10], [1, 2, 3, 5, 8, 9, 10], [0, 1, 2, 5], [4, 6, 10], [0, 2, 3, 10], [2, 4, 5, 9, 10], [0, 1, 2, 6, 8, 10], [0, 4, 5, 6, 7]]
。
今私がする必要があるのは、各内部リストから一意の番号を選択できる方法の数を数えることです。これにより、要素が 2 回選択されず、0 から n-1 までの各番号がすべての選択の中で 1 回だけ選択されます。最初の入力例では、これは自明3! = 6
です。しかし、2 番目の例では、有効な選択の数を数える方法がわかりません。彼らは2番目の入力に対して7588という答えを出しますが、その答えに到達する方法がわかりません。
[0,...,n-1] のすべての順列を見つけて、それらがセット メンバーシップに基づいて有効な組み合わせであるかどうかを確認するという力ずくの方法を既に試しましたが、遅すぎて、実際にコンピュータをクラッシュさせてしまいました。11! = 39916800
順列を反復しようとしました。だから私がする必要があるのは、これを数えるより効率的な方法を見つけることです.
これまでの私のコードは次のとおりです。現在実行しているのは、標準入力からの入力を設定と呼ばれるリストのリストに解析し、それを標準出力に出力することだけです。
def main():
t = int(raw_input())
from itertools import repeat
for _ in repeat(None, t):
n = int(raw_input())
preferences = [[] for _ in repeat(None, n)]
for student in xrange(n):
row = map(int, raw_input().split())
for i in xrange(len(row)):
if row[i] == 1:
preferences[student].append(i)
print preferences
if __name__ == '__main__':
main()
これを効率的にカウントするために使用できる方法はありますか? ヒント/ヒントは大歓迎です。誰かが私のために問題を解決してくれるとは思っていません。私はこれにどのようにアプローチすべきかについて混乱しています。