Zut_round 6(線形1次元dp)

質問A-最長の昇順サブシーケンス

最長の昇順サブシーケンステンプレートの質問
状態表現:セット:各数値を立ち上がり端とする有限セット
属性:最大
状態計算:dp [i] = dp [j] + a [i]> a [j]?1: 0;
ACコード:

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1010;
int n;
int a[N];
int dp[N];
int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)cin >> a[i];
	int ans = 0;
	for (int i = 1; i <= n; i++)
	{
		dp[i] = 1;
		for (int j = 1; j < i; j++)
		{
			if(a[j]<a[i])
			dp[i] = max(dp[i], dp[j] + 1);
		}
		ans = max(dp[i], ans);
	}
	cout << ans << endl;
	return 0;
}

質問B-1次元線形dp ++

かわいそうなウサギは、昔、人生最大の打撃を受けたと言われています。亀に負けた後、落ち込んで復讐を誓ったので、杭州西社のある農園に隠れて、頑張って練習しました。 、休むことなく一定速度(VR m / s)で実行できます。ウサギはいつも、恥ずかしがるために亀に良いレッスンを教える機会を見つけたいと思っていました。
最近、HDUは創立50周年を迎え、社会のすべての有名人が砂に集まり、ウサギもこの機会に亀に挑戦しました。タートルは勝つ見込みがほとんどないことを知っていますが、世論の圧力のために挑戦を受け入れることしかできません。
ゲームは長さLメートルのまっすぐな道を舞台にしています。ルールはとてもシンプルです。最初にフィニッシュラインに到達した人が勝ちます。
前回の勝利以来、この亀は有名な亀になり、一部のゴシップ雑誌では「動物界の劉翔」と呼ばれています。絶え間ない広告があり、手元にたくさんの節約があります。再びウサギを獲得できるようにするために、カメは最先端の武器である「リトルフライングピジョン」ブランドの電気自動車を購入するために費用を惜しみませんでした。この車は電気があればVT1 m / sの速度で「スピード」できます。バッテリーの容量が限られているのは残念です。完全に充電されるたびにCメートルの距離しか移動できません。その後は足でしかペダルを踏むことができません。亀の速度はVT2m / sです。さらに、亀は滑走路にあります。敷地内には電気自動車を充電するための電源ステーションが多数設置されており、その中でも充電にはT秒かかります。もちろん、亀が充電ステーションを通過するときは、充電するかしないかを選択できます。
レースが始まろうとしています。スタートラインには、満タンの電気自動車を持ったウサギとカメが並んでいます。あなたの仕事は、カメが勝ち、ベストプランで一定速度で走れるかどうかを判断するプログラムを書くことです。ウサギ
入力
この問題は、ファイルの終わりに試験、くださいプロセスの複数のセットを含む各試験は4行で構成されています。
最初の行は、整数Lであるが、滑走路の全長を示し、
2行目は三つの整数それぞれN、C、Tを含有します。充電ステーションの数、電気自動車が完全に充電されてから移動できる距離、および各充電に必要な時間
。3行目も3つの整数VR、VT1、VT2で、それぞれウサギの走行速度と電気自動車を運転するカメの速度を表します。 、電気自動車を漕ぐ亀の速度
4行目には、N(N <= 100)の整数p1、p2 ... pnが含まれています。これらはそれぞれ、滑走路の始点からの各充電ステーションの距離を表します。ここで、0 <p1 <p2 <... <pn <L
、各数値は32です。ビット整数の範囲内。タートルが勝つ可能性が高い場合、
OutPutは
「なんて残念なウサギだ!」という行を出力します。それ以外の場合は、「Good job、rabbit!」の行を出力します。
タイトルデータは、カメとウサギが同時に到着しないことを保証します。

タイトルは亀とうさぎを意味します

アイデア:
分析、2つの問題を検討します。1。状態の表現2.状態の計算。
状態式:1セットを決定する:開始点と終了点をガソリンスタンドと見なす場合、問題は有限セットを見つける問題です。開始点から各ガソリンスタンドまでの
時間の問題です。2属性:min最短時間を見つけます。
状態計算:
dp [ i]は、始点から各ガソリンスタンドまでの最短時間、つまり、始点から最後のガソリンスタンドまでの最短時間+最後のガソリンスタンドから現在のガソリンスタンドまでの時間を表します。

ACコード:

#include<iostream>
#include<algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
int N, T, C, L;
int V, V1, V2;
double dp[110];
int p[110];
int main()
{
   while (cin >> L)
   {
   	cin >> N >> C >> T;
   	cin >> V >> V1 >> V2;
   	for (int i = 1; i <= N; i++) cin >> p[i];
   	p[0] = 0; //起点
   	p[N + 1] = L;  //终点
   	dp[0] = 0;
   	double t1, t2, mi; //t1 兔子到终点所用时间  
   	for (int i = 1; i <= N + 1; i++)
   	{
   		mi = INF; //先赋值为无穷大
   		for (int j = 0; j < i; j++)
   		{
   			int dis = p[i] - p[j];
   			if (dis > C)
   				t2 = 1.0 * C / V1 + 1.0 * (dis - C) / V2;
   			else t2 = 1.0 * dis / V1;
   			t2 += dp[j];    //加上前面所用时间
   			if (j) t2 += T;  //如果不是起点 需要加上加油时间
   			mi = min(t2, mi);
   		}
   		dp[i] = mi;
   	}
   	t1 = 1.0 * L / V;   //兔子到达终点用时
   	if (t1 > dp[N + 1]) cout << "What a pity rabbit!" << endl;
   	else cout << "Good job,rabbit!" << endl;
   }
   return 0;
}

質問C-カエルのジャンプ

カエルは現在、座標軸Oxの点0にいます。次のアルゴリズムでジャンプします。最初のジャンプは右に1ユニット、2番目のジャンプは左にbユニット、3番目のジャンプは右に1ユニット、4番目のジャンプは左にbユニットというように続きます。 。

正式に:

カエルが(現在のジャンプの前に)偶数回ジャンプした場合、カエルは現在の位置xから位置x + aにジャンプします。
それ以外の場合は、現在の位置xから位置x-bにジャンプします。
あなたの仕事は、kがジャンプした後のカエルの位置を計算することです。

しかし…もう1つ。あなたはtの異なるカエルを見ているので、tの独立した質問に答えなければなりません。

質問:カエルは開始点から左にaジャンプする回数が奇数回、bが偶数回ジャンプし
ます。K回後のカエルの位置について質問してください。

アイデア:パリティによると

コード:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
ll a, b, k;
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		cin >> a >> b >> k;
		if (k & 1)
			cout << (a - b) * (k /2)+a << endl;
		else cout << (a - b) * (k / 2)  << endl;
	}
	return 0;
}

D题–邪魔された人々

ベルラトフのメインストリートにn戸のアパートがある家があります。Vovaは毎晩この家を見ています。家は、n個の整数a1、a2、…、anの配列として表すことができます。ここで、i番目のフラットでライトがオンの場合はai = 1、それ以外の場合はai = 0です。
Vovaは、1 <i <nかつai-1 = ai + 1 = 1かつai = 0の場合に限り、i番目のアパートの人々は邪魔されて眠ることができないと考えています。
Vovaは、次の質問に関心を持っています。正確にkのペアごとに異なるアパートの人々がライトをオフにした場合、誰も邪魔されないようにするための最小数kはいくつですか。あなたの仕事はこの数kを見つけることです。

入力入力
の最初の行には、1つの整数n(3≤n≤100)が含まれています—家のアパートの数です。
入力の2行目には、n個の整数a1、a2、…、an(ai∈{0,1})が含まれています。ここで、aiはi番目のフラットの光の状態です。

出力
1つの整数のみを出力します—正確にkのペアごとに異なるフラットの人々がライトをオフにした場合に誰も邪魔されないように最小数k。

質問の意味:
n世帯あり、ライトが点灯している場合は1、それ以外の場合は0を意味します
。ai-1= ai + 1 = 1およびai = 0の場合。つまり、ある世帯が夜間にライトをオフにした後も、2つの隣人はオンのままです。そうすると、この家は邪魔されます。
みんなの家が邪魔されないように、少なくともいくつかの照明を消してもらいます。

データの量は少なく、列挙するだけです。
コード:

#include<iostream>
using namespace std;
int n;
int a[110];
int main()
{
	cin >> n;
	for (int i = 0; i < n; i++)cin >> a[i];
	int ans = 0;
	for (int i = 1; i < n - 1; i++)
	{
		if (a[i - 1] == 1 && a[i] == 0 && a[i + 1] == 1)
		{
			ans++;
			a[i + 1] = 0;
		}
	}
	cout << ans << endl;
	return 0;
}

補足する大量のデータ!

Eグッドアレイ

他のすべての要素の合計に等しい要素が配列にある場合は、配列をgoodと呼びましょう。たとえば、配列a = [1,3,3,7]は、合計1 + 3 +3に等しい要素a4 = 7があるため、適切です。

n個の整数で構成される配列が与えられます。あなたの仕事は、この配列のすべてのインデックスjを出力して、配列からj番目の要素を削除した後にそれが適切になるようにすることです(このようなインデックスをniceと呼びましょう)。

たとえば、a = [8,3,5,2]の場合、適切なインデックスは1と4です。

a1を削除すると、配列は[3,5,2]のようになり、適切です。
a4を削除すると、配列は[8,3,5]のようになり、問題ありません。
すべての削除を個別に検討する必要があります。e。要素を削除し、結果の配列が適切かどうかを確認して、要素を配列に戻します。

InPut
入力の最初の行には1つの整数n(2≤n≤2・105)が含まれています—配列aの要素の数です。

入力の2行目には、n個の整数a1、a2、…、an(1≤ai≤106)—配列aの要素が含まれています。

OutPut
最初の行に1つの整数k—配列aのインデックスjの数を出力します。これにより、配列からj番目の要素を削除した後、適切になります(つまり、適切なインデックスの数を出力します)。

2行目には、k個の異なる整数j1、j2、…、jkを任意の順序で出力します—配列aの優れたインデックス。

配列aにそのようなインデックスがない場合は、最初の行に0を出力し、2番目の行を空のままにするか、まったく出力しないでください。
入力
5
2 5 1 2 2
出力
3
4 1 5

入力
4
8 3 5 2
出力
2
1 4

入力
5
2 1 2 4 3
出力
0

アイデア:質問の意味は、配列から任意の番号を削除して、残りの番号に他の番号の合計と等しい番号が含まれるようにし、最後に実行可能なすべての添え字を出力することです。
structを使用して、添え字と値を保存し、値を比較して並べ替えとトラバースを行うことができます。

コード:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 2e5 + 10;
typedef long long ll;
struct node
{
	int x,id;
	bool operator <(const node &S)const 
	{
		return x < S.x;
	}
}a[N];
int b[N];
int main()
{
	int n;
	ll sum = 0;
	cin >> n;
	for (int i = 1; i <=n; i++)
	{
		cin >> a[i].x;
		sum += a[i].x;
		a[i].id = i;
	}
	sort(a + 1, a + 1 + n);
	int k = 0;
	for (int i = 1; i < n; i++)
	{
		if (sum - a[i].x == 2 * a[n].x)
			b[++k] = a[i].id;
	}
	if (sum - a[n].x == 2 * a[n-1].x)
		b[++k] = a[n].id;
	cout << k << endl;
	for (int i = 1; i <= k; i++)
	{
		if (i == k)
			cout << b[i];
		else cout << b[i] << " ";
	}
	return 0;
}

おすすめ

転載: blog.csdn.net/weixin_46750633/article/details/105455705