[質問の解決策] CSP-Xiaomingは学校に通っていません-(線形部分)

トピックの背景

韓東大学校付属の光明区は最近、「ウィズダムブライト」と呼ばれるスマートシティプロジェクトを実施しました。特に運輸分野では、「スマートブライト」ターミナルを通じて、現在の光明区のすべての信号機の状態を確認できます。Xiao Mingの学校には、「Wisdom Bright」端末も設置されていました。XiaoMingは、この端末から提供された情報を使用して、学校から家に帰るのにかかる時間を見積もりたいと考えていました。

問題の説明

学校が終わったとき、シャオミンはすでに帰路を計画していて、さまざまな道路区間を通過する時間を予測することができました。同時に、シャオミンは、学校に設置された「ウィズダムブライト」ターミナルを介して、出発時に道路を通過するすべての信号機の状態を確認しました。今回シャオミンが家に帰るのに必要な時間を計算するのを手伝ってください。

入力フォーマット

入力の最初の行には、スペースで区切られた3つの正の整数r、y、gが含まれており、信号機の設定を示しています。これらの3つの数値はいずれも10 ^ 6を超えません。
  入力の2行目には、正の整数nが含まれています。これは、XiaoMingが通過した道路セグメントと信号機の総数を表します。
  次のn行、各行には、スペースで区切られた2つの整数kとtが含まれています。k = 0は、道路のセクションの後、t秒かかることを意味します。tは10 ^ 6を超えません。それぞれ、k = 1、2、3の場合、出発時刻と信号機の状態を意味します。は赤色光と黄色光、緑色光であり、カウントダウン表示に表示される数値はtであり、tはそれぞれr、y、gを超えない。

出力フォーマット

今回、シャオミンが学校から家に帰るのにかかった時間を示す数字を出力します。

サンプル入力

30 3 30
8
0 10
1 5
0 11
2 2
0 6
0 3
3 10
0 3

サンプル出力

46

サンプル概要

シャオミンは最初に道路の最初のセクションを通過しました。これには10秒かかりました。最初の信号が出たときは赤信号で、残り5秒です。シャオミンが交差点に到着したとき、この信号はすでに青信号に変わっており、直接通過するのを待つ必要はありません。次に、道路の2番目のセクションを通過します。これには11秒かかります。2つ目の信号が始まったときは黄色で残り2秒でした。シャオミンが交差点に到着したとき、信号は赤信号に変わり、残り11秒でした。次に、道路の3番目と4番目のセクションを9秒で通過します。3つ目の信号が始まったときは青信号で残り10秒でした。シャオミンが交差点に到着したとき、信号はすでに赤信号に変わっていて、残り2秒でした。道路の最後のセクションを通過した後、3秒かかります。合計10+ 11 + 11 + 9 + 2 + 3 = 46秒。

評価のユースケースの規模と慣習

一部のテストポイントには特別なプロパティ
  があります。*最初の2つのテストポイントには信号灯がありません。
  テストポイントの入力データスケール:
  *最初の6つのテストポイントは、n≤10^ 3であることを保証します。
  *すべてのテストポイントはn≤10^ 5を保証します。

アルゴリズムのアイデア

緑→黄→赤の3色のライトをサイクルと考えてください。各信号を通過するときは、この時点で表示してください。ランプサイクル街のどの位置を通過できるのは緑色のライトだけで、残りは待つ必要があります。
ここに画像の説明を挿入

コードの説明

1. k = 1
の場合、直進します。2。それ以外の場合は、タイトルで指定された条件が最初の瞬間特定のカラーランプのカウントダウン時間、次にランプが入っている最初の瞬間を見つけますランプサイクル真ん中の時間位置、そして合計経過時間を考慮すると、現在の位置を見つけることができますランプサイクルそれはどこにある?

#include<iostream>
using namespace std;

void forward(long long int x);

long long int r, y, g, n, k, t;
long long int time = 0, light = 0;

int main()
{
	scanf("%lld%lld%lld", &r, &y, &g);
	scanf("%lld", &n);
	light = r + y + g; //灯光周期
	while (n--)
	{
		scanf("%lld%lld", &k, &t);
		if (k == 0)
		{
			time += t;
		}
		else if (k == 1)//红灯
		{
			forward((time + light - t) % light);
		}
		else if (k == 3)//绿灯
		{
			forward((time + g - t) % light);
		}
		else if (k == 2)//黄灯
		{
			forward((time + g + y - t) % light);
		}
	}
	printf("%lld", time);
	return 0;
}

void forward(long long int x)
{
	if (x >= g)       //红灯,等待
	{
		time += light - x;
	}
	return;
}

結果分析1

スコアは100ポイント、時間は78ミリ秒、スペースは2.539MB、時間計算量はO(N)です。

また、ソフトウェアエンジニアリングと原理の知識に基づいて改善することもでき、データ構造を巧妙に使用することで循環的複雑度を減らすことができます。

#include<iostream>
using namespace std;

void forward(long long int x);
long long int loop_light[4] = { 0 };
long long int r, y, g, n, k, t;
long long int time = 0, light = 0;

int main()
{
	scanf("%lld%lld%lld", &r, &y, &g);
	scanf("%lld", &n);
	light = r + y + g; //灯光周期
	loop_light[1] = light;
	loop_light[2] = g + y;
	loop_light[3] = g;
	while (n--)
	{
		scanf("%lld%lld", &k, &t);
		if (k == 0)
		{
			time += t;
		}
//  1. 高级写法
		else
		{
			forward((time + loop_light[k] - t) % light);
		}
	}
	printf("%lld", time);
	return 0;
}

void forward(long long int x)
{
	if (x >= g)       //红灯,等待
	{
		time += light - x;
	}
	return;
}

結果分析2

スコアは100ポイント、時間は78ミリ秒、スペースは2.535MB、時間計算量はO(N)です。(最適化はあまりないようです...)

おすすめ

転載: blog.csdn.net/weixin_44092088/article/details/109863978