Week4-ジョブ

DDLの恐怖 - A


質問の意味:

ZJMがありますn個のジョブは、各ジョブには、独自のDDLを持ってZJMは、DDLの前に仕事をしていない場合は、教師がすべての通常ポイントをこの仕事が差し引かれます。
だから、ZJMはできるだけビット以下の点をバックルして宿題の順序を調整する方法を知りたいです。
彼を助けてください!

入力:

T検定の入力。最初の入力ラインは、テストケースの数で発見された、単一の整数Tです。
各テストケースは、正の整数Nを開始する(1 <= Nは<= 1000)、 ジョブの数を示します。
次に、2本のライン。最初の行は、DDL、バックル点を表すN個の整数を含む次の行を表すN個の整数を含みます。

出力:
各テストケースについて、あなたは最小合計スコアの出力、各試験ラインを減らす必要があります。


アイデア:

これは既知の演習は、貪欲な指標は、問題を見つける必要があり貪欲アルゴリズムです。各DDL完了時間は、高得点の仕事を優先し、1です。この時間は、スコアが同じであれば、その後、DDL、最低から最高までDDL同じスコアを検討し、スコアを降順にソートする必要があります。スコアスコアDDLおよび構造を構成することができます。バックに前方からのTトラバースによれば、それはi番目のDDLのためのものである、貪欲な指標を探す時間が利用されているかどうかBOOLの配列を使用し、アイドル時間後のタイムスケジュールを検索します。


要約:

この質問はサンプルのみが渡され、それでもWAが同じスコアは、さらにソートの必要性を考慮していなかった後にスコアを注文を検討し始めています。貪欲な指標のためには、特定の状況のた​​めに重大な考慮されなければならない同じことを正当化する必要があります。


コード:

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
#define _for(i,a,b) for(int i=a;i<b;i++)

struct ZJM
{
	int ddl;
	int score;
}z[1010];
bool vis[1010] = { false };
int cmp(const ZJM z1, const ZJM z2)
{
	if (z1.score == z2.score)
		return z1.ddl < z2.ddl;
	return z1.score > z2.score;

}

int main()
{
	int T,n;
	int a;
	cin >> T;
	_for(i, 0, T)
	{
		int count = 0;
		int a;
		cin >> n;
		_for(i, 0, n)
		{
			cin >> z[i].ddl;
		}
		_for(i, 0, n)
		{
			cin >> z[i].score;
		}
		sort(z, z + n,cmp);
		memset(vis, 0, sizeof(vis));
		_for(i, 0, n)
		{
			for (a = z[i].ddl; a >= 1; a--)
			{
				if (vis[a] == false)
				{
					vis[a] = true;
					break;
				}
			}
			if (a == 0) count += z[i].score;
		}
		cout << count << endl;
	}
	return 0;
	
}

B - 4つの列

質問の意味:

ZJMは、4つの列A、B、C、Dを有し、各列は、桁数を有するN。ZJMそれぞれの列番号から取られた数が、彼はそのような4と0の数、そのプログラムのどのように多くの種類を知っていただきたいと思います。
場合は、列の数が異なる数として扱うために、数字の同じ複数有しています。

入力:
最初のライン:N(列の数の数を表す)(1≤n≤4000)
次のn行目、4つの数字のi番目の行、列A、B、C、Dの各数i番目の桁(ない以上28以下の電力に数字2)

出力:
異なる組み合わせの出力数。


アイデア:

開始によって話さ年配、A +列挙列の列Bの数は、その後、列の数は、列C + Dの数を列挙する AとBに登場回数次いでC + Dの逆数を算出します しかし、コードまたは誤って複雑さを書くことはO(N ^ 4)であります

_for(i, 0, n*n)
	{
		_for(j, 0, n * n)
		{
			if (sumab[i] == -sumcd[j])
				count++;
		}
	}

もちろん、確かにTE、複雑さを軽減するために二分法を考慮し、この時間は、最初の小から大までsumcdすべてのデータC + D配列を保存するために列の数を列挙し、その後sumabターン、初期化の開始を列挙することです和を見つけるsumcd [中間]は、再度、最小位置0に等しいとし、端部は、次いで、(N-1)*(N-1)の開始が0であり、終了2時間、sumabを使用する[I]が比較されます同じ番号が複数回表示された場合循環は、sumcdが発注されているので、完全なトラバーサルsumabは、番号の行で取得するようなっている右まで追加します。

コード:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define _for(i,a,b) for(int i=a;i<b;i++)
#define MAXN 4000
int a[MAXN], b[MAXN], c[MAXN], d[MAXN],sumab[MAXN*MAXN],sumcd[MAXN*MAXN];
int main()
{
	int count = 0;
	int n;
	cin >> n;
	_for(i, 0, n)
	{
		cin >> a[i] >> b[i] >> c[i] >> d[i];
	}
	int k = 0;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			sumab[k] = a[i] + b[j];
			sumcd[k] = c[i] + d[j];
			k++;
		}
	}
	sort(sumcd, sumcd + k);
	for (int i = 0; i <k; i++)
	{
		int start =0, end =k-1;
		while (start < end)
		{
			int mid = (start + end) >> 1;
			if (sumab[i] + sumcd[mid] >= 0) 
			{
				end = mid;
			}
			else start = mid + 1;
		}
		while (sumab[i] + sumcd[start] == 0 && start < k)
		{
			count++;
			start++;
		}
	}
	cout << count << endl;
	return 0;

}

TTの謎の贈り物

質問の意味:

概要アレイと[I] [i]を数Nアレイの猫を与えられ、新しいアレイANSが生成されます。これは、任意のI、Jのための新たな配列として定義され、iがjは=され、あるANS [] = ABS(猫[I] - 猫[J])] 1 <= I <J <= N. この新しい配列は、次いで、中央値は、位置番号に対応するソート(1 + LEN)/ 2であり、中央値を決定し、「/」丸めあります。

入力:
入力の複数のセットは、各入力1 Nは、数N、N猫、猫の入力シーケンスのその後長さを表現[I] <= 1E9 、3 <= N <= 1E5。

出力:
出力新しい配列ANS中央値。


アイデア:

昇順に猫アレイ、中央値順位がより中央値ランキングを与えるために2分ごとにランキングで知られている(N *(N-1)+ 1/2)/ 2対順位未満である場合この番号の代わりに中央値は、中央値よりも小さい場合、それ以外の場合は中央値よりも大きくなっています。次に、2つの目標値Pを見つけ、その後、ランキング求めます。ANS配列要素が猫[J] -cat [I](I <J)であり、次いで、猫を満たす欲求は、数字のすべてのタプルのために[J] -cat [I] <= Pさとなります。転位により、[I]猫[J] <= P +猫を得、そしてそれらはランクを得るために、私を満たす数jを列挙する。バイナリ検索を使用する、最後出会う猫[J]> = P + CATの位置[I]は、Jの最大値が得られるランキング;各Jランクは、累積最大値に等しく、Iを減算しました。あなたが正中線を見つけるまで、そして、比較ランキングランキングの中央値を算出しました。

要約:

1.この質問はこれ以上の実用的な機能の二分法があるため、二部希望の最初のラウンドは、オンラインで見るために二回半分に、比較についてです。だから私は、この発見
(1)、binary_search(BEG、終わり、のvalを
[、BEG終了]の間のvalを見つけるためにバイナリサーチの方法で、ブール変数を返し、戻り真検索、返し偽を見つけることができません。
(2)、LOWER_BOUNDは(BEG、端、valは)
最後に、最初の[非減少配列を指すイテレータを返す)第一以上(> =)位置のValです。
(3)、UPPER_BOUND(BEG、端、valが)
非減少配列を指すイテレータを返す[最初、最後)の最初のもの(>)位置のValよりも大きいです。
オリジナルリンクします。https://blog.csdn.net/xzymmd/article/details/83902281
これらの場所を見つけるために半分の使用です。そして、これらの機能の原理でどのように二半分私に知らせてください。
時間制限2.ためには、複数のTEが得られCINで始まる、私はそれが半分の理由だと思った良い数回を探して、ビットを変更、またはTE、それはscanf関数を通過してみました。
ここに画像を挿入説明
その後、CINの効率を向上させることができる友人を学んだIOS :: sync_with_stdio(false)をお願いします。
この質問は、私は、多くの恩恵を受けた実践的な知識の多くのことを学びましたので、短いです。

コード:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

int main()
{
	int n;
	int start, end, mid, median, rank,mid1,ans,ans1;
	while (cin >> n)
	{
		int cat[100002];
		for (int i = 0; i < n; i++)
		{
			scanf("%d",&cat[i]);
		}
		sort(cat, cat + n);
		ans=-1;
		start = 0;  //绝对值最小只为0
		end = cat[n - 1] - cat[0]; //最大的数
		median = (1 + n * (n - 1) / 2) / 2; //中位数所在位置
		while (start <= end)
		{
			mid = (start + end) / 2;
			rank = 0;  //初始化位置
			for (int i = 0; i < n; i++)
			{
				int temp=cat[i] + mid; 
				int l = 0, r = n-1;
				ans1=-1;
				while (l <= r)
				{
					mid1 = (l + r)/2;
					if (cat[mid1] <= temp)
					{
						ans1=mid1;
						l=mid1+1;
					}

					else r = mid1 - 1;
				}
				if(ans1!=-1)
					rank+=ans1-i;
			}
			if(rank<median)
			{
				start=mid+1;
			}
			else
			{
				ans=mid;
				end=mid-1;
			}
			
			
		}
		cout << ans << endl;

	}

	return 0;
}

リリース7件のオリジナルの記事 ウォンの賞賛0 ビュー125

おすすめ

転載: blog.csdn.net/weixin_44465341/article/details/104950977