【問題解決レポート】2020年ブルーブリッジカップグループBのニンニク乗客が空欄を埋めたシミュレーション結果:アップル

問題の説明

3030個のバスケットがあり、各バスケットには複数のリンゴが含まれています。バスケット内のリンゴの数の順序が示されています。

次に、リンゴを子供たちに配布する必要があります。各子供は、1つのバスケットから3つのリンゴを取り出すか、隣接する3つのバスケットのそれぞれから1つのリンゴを取り出します。

Appleは存続することができ、さまざまな持ち方がさまざまな答えにつながります。たとえば、シーケンス3 1 3の場合、2つの子に割り当てて0 1 0にすることができます。また、1つの子に割り当てて2 0 2にすることもできます。この時点では、分割できなくなります。したがって、答えは22です。

次のシーケンスでは、最大で何人の子供を共有できますか?


あなたが最も多くまたは最も少なくしたい限り、95%はワイドサーチまたはディープサーチのアイデアです

インターネット上には貪欲なソリューションを使用しているブログがたくさんありますが、これはまったく正しくありません。この質問は貪欲であり、例を示すことしかできません。トリッキーなポイントでデータを変更するのは誤りです。

正しい考えはDFSです。数値を取得する操作は、単一の-3または隣接する3つの-1の2つだけです。その後、ディープサーチを使用して各可能性をシミュレートおよびトラバースする限り、自然に最小値を見つけることができます。


注:単に検索を使用して実行する場合、各番号は隣接する2つをそれぞれマイナス1に取り、番号から3を引いた操作を行う必要があります。つまり、コンピューターの場合、3の30乗を実行する必要があります。それでも非常に遅いので、剪定で最適化する必要があります。


参照コード

#include<bits/stdc++.h>
using namespace std;

int ans = 0; 
int a[117] = {
    
    7,2,12,5,9, 9,8,10,7,10, 5,4,5,8,4, 4,10,11,3,8, 7,8,3,2,1, 6,3,9,7,1};
int sum[117];

void dfs(int idex, int num) {
    
    
	if(idex == 30) {
    
    
		ans = max(ans, num);
		return;
	}
	if(sum[idex] / 3 + num < ans) return; 	//剪枝优化
	//不公用
	dfs(idex+1, num+a[idex]/3);
	//往后公用 
	if(idex+2 < 30) {
    
    
		int min_num = min(a[idex], a[idex + 1]);
		min_num = min(min_num, a[idex+2]);		//共用最多能分几个
		for(int k = 1; k <= min_num; k++) {
    
    
			for(int i = 0; i < 3; i++) a[idex+i] -= k;
			dfs(idex+1, num+a[idex]/3+k);
			for(int i = 0; i < 3; i++) a[idex+i] += k;
		} 
	} 
}

int main() {
    
    
    for(int i = 29; i >= 0; i--) sum[i] = sum[i + 1] + a[i];
    for(int i = 0; i < 30; i++) cout << sum[i] << ' ';
    dfs(0, 0);
    cout << ans << endl;
    return 0;
}


未来が期待できる

ここに写真の説明を挿入

おすすめ

転載: blog.csdn.net/weixin_43899069/article/details/109098805