1. 程式人生 > >【 OJ 】 HDOJ1052 18年12月19日22:38 [ 46 ]

【 OJ 】 HDOJ1052 18年12月19日22:38 [ 46 ]

轉自 https://www.cnblogs.com/Open_Source/archive/2010/07/09/1904940.html

解題思路:貪心演算法。根本思想是要讓田忌花最小的代價來勝一每一場,讓齊王花最大的代價來勝每一場。(“代價”可以用比較的兩匹馬的權值之差來形象地表示)

首先將兩人的馬排序。

(讓田忌每一匹馬實現自己的最大價值)這時如果田忌最劣的馬是所有中最劣的,就讓它跟齊王最強的比較(這時對於田忌的這匹劣馬來說並不會比其它的情形壞,因為它註定要輸)齊王的最強馬沒了,對於田忌其他馬來說勝率更大,如果田忌最劣的馬不是最劣的,說明這匹馬強於齊王最劣的,那就讓它們比較,讓田忌勝出(按照貪心仔細想想,如果讓每一匹馬的價值最大,其實操作應該更加複雜,假設田忌最差的是t_low,速度為80,齊王最差的是k_low1,速度68,第二差的k_low2 速度79,如果需要價值最大化,應該用t_low去勝K_low2)

(但是實際上並不需要,因為t_low2速度大於t_low1,前兩場無論田忌怎麼出t_low1和2一定勝,但是如果K_low3速度大於t_low3,最終還是2勝一敗,雖然實現了最大價值,但是並沒有改變結果)


原文:https://blog.csdn.net/lawrencesgj/article/details/8001638 

*
貪心策略:
1,如果田忌的最快馬快於齊王的最快馬,則兩者比。
(因為若是田忌的別的馬很可能就贏不了了,所以兩者比)
2,如果田忌的最快馬慢於齊王的最快馬,則用田忌的最慢馬和齊王的最快馬比。
(由於所有的馬都贏不了齊王的最快馬,所以用損失最小的,拿最慢的和他比)
3,若相等,則比較田忌的最慢馬和齊王的最慢馬
3.1,若田忌最慢馬快於齊王最慢馬,兩者比。
(田忌的最慢馬既然能贏一個就贏唄,而且齊王的最慢馬肯定也得有個和他比,所以選最小的比他快得。)
3.2,其他,則拿田忌的最慢馬和齊王的最快馬比。
(反正所有的馬都比田忌的最慢馬快了,所以這匹馬必輸,選貢獻最大的,幹掉齊王的最快馬)

我的是從最慢的馬開始弄的....思路基本相同

#include<iostream>
# include<algorithm>
using namespace std;
int t[1000], k[1000];
int main(void) {
	int n;
	cin >> n;
	while (n) {
		for (int i = 0; i < n; i++)
			cin >> t[i];//田的馬
		for (int i = 0; i < n; i++)
			cin >> k[i];//王的馬
		sort(t, t + n);
		sort(k, k + n);
		int tlow, klow, tfast, kfast;
		tlow = klow = 0;
		tfast = kfast = n - 1;
		int twin, kwin; twin = kwin = 0;
		for (int i = 0; i < n; i++) {
			if (t[tlow] < k[klow]) {//最差對王最強
				tlow++; kfast--; kwin++;
			}
			else if (t[tlow] == k[klow]) {
				//看快馬
				if (t[tfast] > k[kfast]) {
					 tfast--; kfast--; twin++;
				}
				else {//快馬相等或者沒有王快都是用慢馬消耗
					if (k[kfast] > t[tlow])kwin++;
					tlow++; kfast--;
				}
			}
			else {//田忌慢馬贏
				tlow++; klow++; twin++;
			}
		}
		cout << (twin - kwin) * 200<<endl;
		cin >> n;//下一輪
	}
	system("pause");
	return 0;
}

下面是我的自檢方法:之前一直AC不了,寫了個自檢來找錯誤案例

# include<iostream>
#include<algorithm>
#pragma warning (disable:4996)
using namespace std;
int t[1010], k[1010];
int R(void) {//偽隨機自檢
	int randn= (rand() % 10) + 1;
	for (int i = 0; i < randn; i++) {
		t[i] = (rand() % 99 )+ 1;
		k[i]= (rand() % 99) + 1;
	}
	return randn;
}
//正確答案
int Y(int n) {
	int  i, awin, bwin, afast, bfast, aslow, bslow;
	sort(t, t + n);
	sort(k, k + n);
	awin = bwin = 0;//記錄贏的次數 
	afast = bfast = n - 1;//標記最快的馬 
	aslow = bslow = 0;//標記最慢的馬 
	for (i = 0; i < n; ++i)
	{
		if (t[aslow] >k[bslow])
		{
			awin++;
			aslow++; bslow++;
		}
		else if (t[aslow] < k[bslow])//用最慢馬消耗國王的最快馬 
		{
			bwin++;
			aslow++; bfast--;
		}
		else//兩匹最慢馬速度相同時 
		{
			if (t[afast] > k[bfast])
			{
				awin++;
				afast--; bfast--;
			}
			else if (t[aslow] < k[bfast])//如果田忌的最快馬不能勝國王的最快馬,則用慢馬消耗 
			{
				bwin++;
				aslow++; bfast--;
			}
		}
	}
	return (awin - bwin) * 200;
}
//我的答案
int My(int n) {
	int tlow, klow, tfast, kfast;
	tlow = klow = 0;
	tfast = kfast = n - 1;
	int twin, kwin; twin = kwin = 0;
	for (int i = 0; i < n; i++) {
		if (t[tlow] < k[klow]) {//最差對王最強
			tlow++; kfast--; kwin++;
		}
		else if (t[tlow] == k[klow]) {
			//看快馬
			if (t[tfast] > k[kfast]) {
				 tfast--; kfast--; twin++;
			}
			else {//快馬相等或者沒有王快都是用慢馬消耗
				if (k[kfast] > t[tlow])kwin++;
				tlow++; kfast--;
			}
		}
		else {//田忌慢馬贏
			tlow++; klow++; twin++;
		}
	}
	return (twin - kwin) * 200;
}
int main()
{
	int nn,time=0;
	while ((time++)<100000) {
		cout << time << endl;
		nn = R();
		int yre = Y(nn);
		int mre = My(nn);
		if (yre != mre) {
			for (int i = 0; i < nn; i++) {
				cout << t[i] << " ";
				if (!((i + 1) % 10))cout << endl;
			}
			cout << "出現答案不同的案例:" << endl;
			cout << "--------------------------------";
			cout << endl << nn << endl;
			cout << "________正確答案:" << yre << endl;
			cout << "________我的答案:" << mre << endl;
			cout << "---------------------------------";
			cout << endl << endl << endl;
			for (int i = 0; i < nn; i++) {
				cout << k[i] << " ";
				if (!((i + 1) % 10))cout << endl;
			}
			system("pause");
		}
	}
	system("pause");
	return 0;
}