P4377 【USACO18OPEN】タレントショーG(貪欲+01バックパック+01企画)

トピックの説明

農場主のジョンは、毎年行われる牛の品評会に参加するために、n 頭の牛 (便宜上 1...n と番号付け) を農業フェアに連れて行きたいと考えています。彼の i 番目の牛の体重は wi 、才能レベルは ti で、どちらも整数です。

到着すると、ファーマー ジョンは今年のダ ニウ ショーの新しいルールに脅迫されました。

(i) 競技会に参加する牛のグループは、合計体重が少なくとも W でなければなりません (これは、単に強い牛だけでなく、強力なチームが競争することを保証するためです)。

(2) 総体重に対する総才能値の比率が最も大きいグループが勝利します。

FJ は、すべての牛の合計体重が W 以上であることに気づき、ルール (1) を満たすチームを送ることができます。そのようなチームで達成できる最適な才能と体重の比率を決定するのを手伝ってください。

入力フォーマット

最初の行は 2 つの整数で、牛の頭数 n と総重量制限 W を表します。

行 2 から (n+1) まで、各行には 2 つの整数があり、行 (i+1) の整数は i 頭の牛の体重 wi と才能レベル t_iti を表します。

出力フォーマット

総重量に対する最大可能総才能値の比率を取得するために、総重量が少なくとも W である牛のグループを使用するように農家に依頼します。

答えが A の場合、出力が整数になるように切り捨てられた 1000A の値を出力します (問題の数値が整数でない場合、四捨五入により整数部分に切り捨てるときに小数点以下がすべて削除されます)。

入力サンプルと出力サンプル

#1 を入力してコピーします

3 15 
20 21 
10 11 
30 31

#1 のコピーを出力します

1066

アイデア:

この質問では考慮すべき条件が 2 つあります。

1. 競技会に参加する牛のグループは、総体重が少なくとも W でなければなりません。

2. 総体重に対する総才能値の比率が最も大きいチームが勝利します

2 番目の条件は、この牛を選択するか選択しないかという問題に属し、これが私の最初の 01 スコア計画問題です。

最初の条件が W 以上の場合、動的計画法を使用できますが、最終結果は dp[W] になります。

#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f, N = 255, WW = 1005;
int n, W;
struct { int w, t; double y; }cow[N];
double dp[WW];
bool check(double x) {
	int i, j;
	for (int i = 1; i <= n; i++) cow[i].y = (double)cow[i].t - x * cow[i].w;//0/1规划的基础思路
	for (int i = 1; i <= W; i++) dp[i] = -INF;
	dp[0] = 0;
	// 0-1背包的思想 一维
	for (int i = 1; i <= n; i++) {
		for (int j = W; j >= 0; j--) { // 当前背包的大小
			if (j + cow[i].w >= W) dp[W] = max(dp[W], dp[j] + cow[i].y); //超过了这个了贪心是否选这个
			else dp[j + cow[i].w] = max(dp[j+ cow[i].w], dp[j] + cow[i].y);
		}
	}
	return dp[W] < 0; // true x大了 我们要使 x尽可能大
}
int main() {
	cin >> n >> W;
	for (int i = 1; i <= n; i++) cin >> cow[i].w >> cow[i].t;
	double L = 0, R = 0;
	for (int i = 1; i <= n; i++) R += cow[i].t;
	for (int i = 0; i < 50; ++i) {
		double mid = L + (R - L) / 2;
		if (check(mid)) R = mid;
		else L = mid;
	}
	cout << (int)(L * 1000) << endl;
	return 0;
}

おすすめ

転載: blog.csdn.net/zhi6fui/article/details/128616811