第12回ブルーブリッジカップの3番目のシミュレーションゲーム-ABC(バイナリ動的計画法)

1.問題の説明:

制限時間:3.0秒メモリ制限:512.0MBこの質問の合計スコア:25ポイント
食料品店の所有者には合計N個のアイテムがあり、各アイテムにはABCの3つの属性の1つ以上があります。食料品店の所有者から商品を購入するには、対応する価格を支払う必要があります。次に、3つの属性ABCのそれぞれが、購入した少なくとも1つのアイテムに表示され、支払われる合計コストが最小になるように、アイテムの購入方法を理解する必要があります。
【入力形式】入力の
1行目に整数Nが含まれています。
次のN行には、整数Cと、アイテムとその属性の購入コストを表す「ABC」のみを含む文字列が含まれています。
【出力形式】
最小コストを表す整数を出力しますとにかくABCの3つの属性が欠落している場合は、-1が出力されます。
[サンプル入力]
5
10 A
9 BC
11 CA
4 A
5 B
[サンプル出力]
13
[評価ユースケースのスケールと規則]
評価ユースケースの50%について、1 <= N <= 20
すべての評価ユースケースについて、1 <= N <= 1000、1 <= C <= 100000

2.思考分析:

①最初は、再帰的方法を使用して、考えられるすべてのスプライシングスキームを試すことを考えました(現在の文字列では、2つの並列状態を持つかどうかを選択でき、2つの再帰的方法で解決できます)が、データ量が多いためです。は10 ^ 5ですが、この問題は動的計画法(暴力的な列挙の条件下での最適化)によって解決する必要があると感じていますが、最初はABCの3つの属性を表すためのより良い方法を見つけられませんでした。 csdnバイナリを使用してABCの3つの属性を表す方法、この老人は非常によく書いていると思います。アイデアは、バイナリ+動的計画法を使用することです。バイナリの4/2/1はの3つの属性を表します。 CBAなので、ABCの3つの属性をサブスクリプトにマップできます。Python言語を使用しているため、長さ8のdpリスト(javaまたはc、c ++の配列に相当)を宣言できます。dp[i]は次のことを意味します。 iの属性の最小コストを持つ。数値iは、現在のアイテムの属性を表します。dp[i]の意味が決定されたら、次の手順は簡単に処理できます。現在のアイテムの属性については、次の手順を実行してください。他の項目に追加して(dp [1] 〜dp [7]をループ)、属性と値が変更されているかどうかを確認します。形成できる値が小さい場合は、位置に対応する値を更新します。属性を追加した後。dp状態遷移方程式は難しくありません。dp[v | j] = c + dp [j](c + dp [k] <dp [v | k])と考えると、cはの値を表します。現在の入力項目vは、現在の入力項目の属性を表します。v| jは、現在の属性をjの代表的な属性を持つ位置に追加して、より低いコストを構成できるかどうかを確認することを意味します。

②暴力的な列挙を利用できるこの問題に遭遇した場合、データ量が多い場合の動的計画法を考え、さらに最適化する方法を検討し、前の状態と現在の状態が通過する可能性があることを明確にする必要があります。多くの場合、どのような導出方法が使用されるかは、いくつかの組み合わせ問題の暴力です。現在の状態を取得するために複数の組み合わせが存在する可能性があります。私の目標はループを通じて最適な状態を見つけることであり、状態遷移は実際には非常に重要です。ステップ、大物のためのリファレンスブログ

3.コードは次のとおりです。

import sys
if __name__ == '__main__':
    dp = [sys.maxsize] * 8
    N = int(input())
    for i in range(N):
        # split函数的返回值就是一个列表
        cur = input().split()
        c = int(cur[0])
        v = 0
        # v记录当前物品具有的属性
        for j in cur[1]:
            # 左移这么多位表示在xxx对应的二进制位上将置为1表示存在这个属性,
            v |= 1 << (ord(j) - ord("A"))
        # 上面的循环结束之后v表示的就是当前输入物品具有的所有属性
        # 长度为8的循环是为了尝试将当前的输入物品属性添加到之前的位置看是否能够构成代价更小的
        for k in range(1, 8):
            # v & k != v表示之前已经具有所有的属性这个时候添加进来一点贡献都没有
            # c + dp[k] < dp[v | k]其中v | k表示将当前的物品添加到k这个位置对应的属性中看是否构成价值更小
            # 或运算的意思是添加当前输入物品的属性到之前的物品属性中
            if v & k != v and dp[k] != sys.maxsize and c + dp[k] < dp[v | k]:
                dp[v | k] = c + dp[k]
        # 取出dp[v]与c中的最小值的那个
        dp[v] = min(dp[v], c)
    # 输出最后一个元素表示具有三种属性的物品花费的最小价值
    print(dp[7] if dp[7] != sys.maxsize else -1)

 

おすすめ

転載: blog.csdn.net/qq_39445165/article/details/115260347