[PAT-A 1068]多くのコインを探します

ここに画像を挿入説明
効果の対象には:
すべてのコインは今Mのものの値を支払うためにこれらの硬貨を使用して値が与えられ、N個のコインがあります。
彼らはそのようなスキームを見るために見つけることができれば、正確にMの合計を支払う硬貨の価値を選択し、そうでない場合、出力NoSolutionするように、尋ねました。
小規模から大出力まで、存在する場合はコインの値を選択するために使用される各種のプログラム、出力辞書順最小のものがある場合に、払い出されます。

思考:
アレイを使用して、Cの値[i]とタイトルの品質W [i]と等価であり、Cとすることができる[i]が格納されており、W [I]。
値の出力を上昇するために要求の対象ので、大型であり、その後、通常動作DPに小さいから第アレイ01バックパックに必要です。
状態遷移方程式DP [I] [V] =
最大{DP [I-1] [V]、DP [I-1] [VW [I] + C [I]}。 これに基づき、二次元を定義アレイの選択[I-1] [V ]、 計算DPに使用[I] [V]ポリシーが選択されています。
選択されたDP [I-1]〜[V ] の選択[I] [V] = 0、 i番目の状態遷移場合ホールド項目を示します。
DP [I-1] [VW [選択された状態遷移であれば I] + C [i]は、 選択[I] [V] = 1、 i番目の項目の選択を示します。
完成DPこの配列を解いた後、最大のDPを選択し、[n]を[V]、開始後方からn個のアイテムはバックパックに各項目かどうかを確認します。

DPなし溶液条件[n]は[M]! = M、 そう長くDP [m]は、mは説明する解決策ではないではないとして、Mの値を支払うことを要求だけで十分なお金の主題以来。
DP配列を解くときに2つのポリシーのサイズが同じであれば、あなたは政策のi番目のアイテムを置くことを選択する必要があります。

ACコード:

//PAT_A 1068
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 10010;
const int maxv = 110;
int w[maxn], dp[maxn][maxv] = { 0 };
bool choice[maxn][maxv], flag[maxn];
bool cmp(int a, int b) {
	return a > b;
}
int main() {
	int n, m;
	(void)scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) {
		(void)scanf("%d", &w[i]);
	}
	sort(w + 1, w + n + 1, cmp);
	for (int i = 1; i <= n; i++) {
		for (int v = w[i]; v <= m; v++) {
			int temp1 = dp[i - 1][v - w[i]] + w[i];//放
			int temp2 = dp[i - 1][v];//不放
			if (temp1 >= temp2) {//保证字典序,如果相等也要选
				choice[i][v] = 1;//选i号硬币
				dp[i][v] = temp1;
			}
			else {
				choice[i][v] = 0;//不选i号硬币
				dp[i][v] = temp2;
			}
		}
	}
	if (dp[n][m] != m)printf("No Solution");
	else {
		int k = n, num = 0, v = m;//看choice数组的第v列
		while (k >= 0) {
			if (choice[k][v] == 1) {
				flag[k] = true;
				v -= w[k];
				num++;
			}
			else flag[k] = false;
			k--;
		}
		for (int i = n; i >= 1; i--) {
			if (flag[i] == true) {
				printf("%d", w[i]);
				num--;
				if (num > 0)printf(" ");
			}
		}
	}
	return 0;
}
公開された142元の記事 ウォンの賞賛1 ビュー4552

おすすめ

転載: blog.csdn.net/weixin_44699689/article/details/104719162