【質問解決】クロニカン

タイトルは、
ミスラフが無限の容量のNカップを持ち、各カップにいくらかの水が含まれていることを示しています。ミスラフはすべての水を飲みたかったが、K杯以上の水を飲みたくなかった。ミストラフができることは、あるカップから別のカップに水を注ぐことだけです。残念ながら、ミスラフは注ぐ2つのカップを選択することが重要です。これは、すべてのカップが彼からそれほど離れていないためです。より正確には、カップiからカップjに水を注ぐために支払われる価格はCijです。ミスラフが支払う必要のある合計金額の最小値を見つけるのに役立ちます。

入力フォーマット入力の
最初の行には、整数NおよびK(1≤K≤N≤20)が含まれています。飲酒グラスの総数とミスラフが飲めるグラスの最大数を示します。次のN行のそれぞれには、N個の整数Cij(0≤Cij≤1e5)が含まれています。i + 1行目のj番目の整数は、i番目のカップとj番目のカップから水を注ぐコストを表します。Ciiが0であることを確認します。

出力形式
整数を出力しますミスラフが支払う必要がある総コストの最小値を表します。

例えば
入力例1
3 3
0 1 1
1 0 1
1 1 0
出力例1
0
たとえば入力2
3 2
0 1 1
1 0 1
1 1 0
出力例2
1
例入力3
5 2
0 5 4 3 2
7 0 4 4 4
3 3 0 1 2
4 3 1 0 5
4 5 5 5 0
サンプル出力3
5
範囲
n <= 20

n <= 20 n <= 20と表示されるため<=2 0、通常は形状を押すだけで
2 n 2 ^ nを直接使用します2n 01の状態は、特定のカップに水があるかどうかを示し
ます水でカップを列挙し、次に水でカップを列挙するたびに、フロントカップを後ろに注いで転送を完了します。
時間の複雑さO(2 n ∗ n 2)O(2 ^ n * n ^ 2)O 22
その後、落ち着くt l e
では、少しトリックを考えてみてください。毎回、状態の「1」をすべて列挙するだけで、
ほとんどパスしません。

コード:

#pragma GCC optimize ("-Ofast")
#include <bits/stdc++.h>
#define maxn 25
#define maxm 2000010
using namespace std;
int n, m, w[maxn][maxn], pos[maxm], power[maxn], num[maxm], dp[maxm];

inline int read(){
    
    
	int s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
	return s * w;
}

int lowbit(int x){
    
     return x & -x; }

int main(){
    
    
	freopen("pb.in", "r", stdin);
	freopen("pb.out", "w", stdout);
	n = read(), m = read();
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= n; ++j)
			w[i][j] = read();
	power[0] = 1, pos[1] = 1;
	for (int i = 1; i <= n; ++i) power[i] = power[i - 1] << 1, pos[power[i]] = i + 1;
	for (int i = 0; i < power[n]; ++i)
		for (int j = i; j; j -= lowbit(j)) ++num[i];
	for (int i = 0; i < power[n]; ++i) dp[i] = 1e9;
	dp[power[n] - 1] = 0;
	int ans = 1e9;
	for (int i = power[n] - 1; i >= 0; --i){
    
     //printf("num[%d]=%d\n", i, num[i]);
		if (num[i] <= m) ans = min(ans, dp[i]);
		for (int s1 = i; s1; s1 -= lowbit(s1)){
    
    
			int j = pos[lowbit(s1)];
			for (int s2 = i; s2; s2 -= lowbit(s2)){
    
    
				int k = pos[lowbit(s2)];
				if (j != k) dp[i ^ power[j - 1]] = min(dp[i ^ power[j - 1]], dp[i] + w[j][k]);
			}
		}
	}
	printf("%d\n", ans);
	return 0;
}

おすすめ

転載: blog.csdn.net/ModestCoder_/article/details/108617938