ダイナミックプログラミングNでc++を表す
7704 ワード
問題は,Nとnumberが与えられた場合,Nと4則演算のみで表す方法で,Nの使用回数の最大値を求める問題である.
e.g.
最大値が4であるため、4を返します.
ここで逆に考えるとNは1個2個3個….仕事でできる数の集合を考えてみましょう.これらのセットに検索する番号がある場合は、作成できる番号を返します.
5が1の場合=
e.g.
dp[0]=5が1の場合
5、55、555などの数値の関数を作成します.
(1)
(2)最初のすべての場合、デフォルト値は
(3)
(4)
e.g.
N=5, number=12
12=5+5+(5/5)+(5/5)
->6個12=55/5+5/5
->5個12=(55+5)/5
->4個最大値が4であるため、4を返します.
ここで逆に考えるとNは1個2個3個….仕事でできる数の集合を考えてみましょう.これらのセットに検索する番号がある場合は、作成できる番号を返します.
5が1の場合=
{5}
2個5時={55, 5+5, 5-5, 5*5, 5/5}
3個5時={555, 5+55, 55+5, 5+5+5, 5-55, 55-5, 5-5-5, 5*55, 55*5, 5*5*5, 5/55, 55/5 , 5/5/5}
ここから,2つの場合に用いられる演算は,3つの場合に用いられる演算に用いられることが分かる.例えば、5が3の場合、{5+5+5}は5が1の場合、{5}と5が2の場合、{5+5}演算が加算される.1.Memoization方式が考えられ、それをdpと表す
vector<unordered_set<int>> dp(8);
(2 Dベクトルを宣言するのではなくunordered_set
を使用するのは、格納された値がソートされる必要がなく、重複する値が複数回書き込まれる必要がないためです)e.g.
N=5, number=12
(ただし&はすべての4則演算を表す)dp[0]=5が1の場合
{5}
--N0
dp[1]=5が2の場合{55, N0 & N0}
--N1
dp[2]=5が3の場合{555, N0 & N1, N1 & N0}
--N2
dp[k]=5がkの場合{555... (k개 만큼), Ni & Nj (i+j+1=k 인 집합)}
2.k個Nの関数を作成する
5、55、555などの数値の関数を作成します.
#include <cmath>
int makeNumber (int N, int idx) {
int answer=0;
while (idx>0) {
idx--;
answer+=N*pow(10, idx);
}
return answer;
}
3.dp[k]に値を保存する
(1)
dp[0]
は、1つのNを使用して数値を作成するので、1(2)最初のすべての場合、デフォルト値は
5, 55, 555, 5555
であるため、2番目に作成されたk개의 N을 만드는 함수
が呼び出されて保存される(3)
i+j+1=k
の場合、1つの数字を抽出してから、4つの演算値をdp[k]
に保存する(マイナス記号と除算に注意)(4)
dp[k].count(number)>0
,すなわちk+1
個Nで作成可能な集合中の要素数の個数が0より大きい,すなわちk+1을 return
for (int k=1; k<MAX; k++) {
dp[k].insert(makeNumber(N, k+1));
for (int i=0; i<MAX; i++) {
for (int j=0; j<MAX; j++) {
if (i+j+1!=k) continue;
for (int op1: dp[i]) {
for (int op2: dp[j]) {
dp[k].insert(op1+op2);
if (op1-op2>0) dp[k].insert(op1-op2);
dp[k].insert(op1*op2);
if (op1/op2>0) dp[k].insert(op1/op2);
}
}
}
}
if (dp[k].count(number)>0)
return k+1;
}
完全なコード
#include <string>
#include <vector>
#include <unordered_set>
#include <cmath>
const int MAX=8;
using namespace std;
int makeNumber (int N, int idx) {
int answer=0;
while (idx>0) {
idx--;
answer+=N*pow(10, idx);
}
return answer;
}
int solution(int N, int number) {
if (N==number) return 1; // 이 경우의 수도 꼭 포함해주어야 함
vector<unordered_set<int>> dp(MAX);
dp[0].insert(N);
for (int k=1; k<MAX; k++) {
dp[k].insert(makeNumber(N, k+1));
for (int i=0; i<MAX; i++) {
for (int j=0; j<MAX; j++) {
if (i+j+1!=k) continue;
for (int op1: dp[i]) {
for (int op2: dp[j]) {
dp[k].insert(op1+op2);
if (op1-op2>0) dp[k].insert(op1-op2);
dp[k].insert(op1*op2);
if (op1/op2>0) dp[k].insert(op1/op2);
}
}
}
}
if (dp[k].count(number)>0)
return k+1;
}
return -1;
}
Reference
この問題について(ダイナミックプログラミングNでc++を表す), 我々は、より多くの情報をここで見つけました https://velog.io/@kimmy/Programmers-Dynamic-ProgrammingN으로-표현-cテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol