問題解決のためのレポートを解決する非常に優れたレポート数:動的プログラミング:コース大規模な操作

この質問は、私は私が撃つことを学んでなかった感謝すべきですか?
サインインして中に入るために、入力と出力のリダイレクトファイルを使用することで、特定のコードは2行です。

	freopen("hwin.txt", "r", stdin);
	freopen("hwoutstd.txt", "w", stdout);

辞書式は本当に陥没......しかし、その間違いは本当に精神的に爆発する......

トピック:

説明
北京大学の暁明学校3年生の学部の学生。彼は、キャンパスコミュニティの多様に参加するのが好きです。終わりに近づいて、この学期は、各コースの締め切りは大きな仕事が来ているが、暁明はまだ開始されていません。各コースは各コースには、大きな仕事の期限を持って、大きな仕事のコースがあります。X日以上の提出期限た場合、彼はXポイントを差し引かれます。各大規模な操作のために、暁明は、完了するために、1日または数日間を過ごすために。彼は複数の同時大規模な操作を行うことができない、彼らは新しいプロジェクトを開始する前に、彼は唯一の現在のプロジェクトに仕上げました。スティーブは、あなたは彼がペナルティポイントを減らすために(大仕事の注文を完了するために)最善の方法をマップ手助けしたいと考えています。

入力
入力は、いくつかの試験サンプルで構成されています。
最初の入力ラインは、試験サンプルの数を表す正の整数T、です。
各試験サンプルについて、最初の正の整数N(1 <= N <=の行動 15) コースの数を表します。
次のN行、列S(せいぜい50文字)を含む各行は、コース名と二つの整数D(作業会議オフ時間)とC(必要とされる大きなジョブ完了時間)を表します。
入力が辞書式順序で表示されるには、プログラムのすべての順序が配置されていることに注意してください。
出力
各テストケースについて、出力対応点の最小順序及びコースの完了。
より最適な解決策がある場合は、プログラムの辞書的に前の出力をしてください。
サンプル入力
2
。3
コンピュータ。3. 3
辞書英語。1 20
数学。3 2
。3
コンピュータ。3. 3
辞書英語。6. 3
数学。6. 3
サンプル出力
2
コンピュータ
数学
辞書英語
。3
コンピュータ
辞書英語
数学を
促す
第二の試験試料を、コース完了順序コンピュータ- >英語- >数学とコンピュータ- > Math->英語は3つのペナルティポイントになりますが、辞書序文でフロントので、我々は、元を選択します。
成形圧力DP、TSPの変種。実際に状態遷移方程式を考え始めて......と考えることができない、本当にTSPモデルを設定し、あなたが話せない場合は、次の
DP [S]をDP [SJ] + C(J)=
C(j)が仕上げSJ jの後に行うことですスコアをバックル。
その後、私は圧力サイクル(* 15 15を意味している?ほとんど作ら列挙)は、最終的なアイデアの配布資料を見たのか分からないように考えていなかったではないでしょう。
次のようにACコードは次のとおりです。

#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
struct info {
	string name;
	int ddl;
	int t;
};
struct node {
	int pre;
	int thisone;
	int act; //all time consumed
	int minscore;
	node() {
		pre = 0;
		thisone = 100;
		act = 0;
		minscore = 0xffffff;
	}
};
int main() {
	int T;
	cin >> T;
	while (T--) {
		node dp[(1 << 15) + 1];
		info hw[15];
		int num;
		cin >> num;
		for (int i = 0; i < num; ++i) {
			cin >> hw[i].name >> hw[i].ddl >> hw[i].t;
			//dp[(1 << i)].act = hw[i].t;
			//dp[(1 << i)].minscore = max(hw[i].t - hw[i].ddl, 0);
			//dp[(1 << i)].thisone = i;
		}
		dp[0].minscore = 0;
		int all = pow(2, num);
		for (int i = 1; i < all; ++i) {
			for (int j = 0; j < num; ++j) {
				if ((i >> j) & 1) {
					if (dp[i].minscore > dp[i & (~(1 << j))].minscore + max(dp[i & (~(1 << j))].act + hw[j].t - hw[j].ddl, 0)) {
						dp[i].pre = (i & (~(1 << j)));
						dp[i].minscore = dp[dp[i].pre].minscore + max(dp[dp[i].pre].act + hw[j].t - hw[j].ddl, 0);
						dp[i].act = dp[dp[i].pre].act + hw[j].t;
						dp[i].thisone = j;
					}
					else if (dp[i].minscore == dp[i & (~(1 << j))].minscore + max(dp[i & (~(1 << j))].act + hw[j].t - hw[j].ddl, 0)) {
						int kl = dp[i].pre, kr = (i & (~(1 << j)));
						vector <int> left;
						vector <int> right;
						left.push_back(dp[i].thisone);
						right.push_back(j);
						while (kl != 0) {
							left.push_back(dp[kl].thisone);
							right.push_back(dp[kr].thisone);
							kl = dp[kl].pre;
							kr = dp[kr].pre;
						}
						reverse(left.begin(), left.end());
						reverse(right.begin(), right.end());
						for (int k = 0; k < left.size(); ++k) {
							//一开始没加这个if
							if (right[k] > left[k]) {
								break;
							}
							if (right[k] < left[k]) {
								dp[i].pre = (i & (~(1 << j)));
								dp[i].minscore = dp[dp[i].pre].minscore + max(dp[dp[i].pre].act + hw[j].t - hw[j].ddl, 0);
								dp[i].act = dp[dp[i].pre].act + hw[j].t;
								dp[i].thisone = j;
								break;
							}
						}
					}
				}
			}
		}
		cout << dp[all - 1].minscore << endl;
		int k = all - 1;
		vector <int> output;
		while (k != 0) {
			output.push_back(dp[k].thisone);
			k = dp[k].pre;
		}
		for (int i = output.size() - 1; i >= 0; --i) {
			cout << hw[output[i]].name << endl;
		}
	}
	return 0;
}

コードへのリンクは、辞書式順序の面で非常に巧妙で見ることが、ありますが、それは標準的なプロセスで撮影することです。
https://blog.csdn.net/yhjpku/article/details/80698249

おすすめ

転載: blog.csdn.net/weixin_44288817/article/details/90554292