[解析アルゴリズムプール]Programmers Nとして表示
生まれながらにしてDPが嫌いな病気があり、
延び延びになっていたDPが今日やっと始まりました
初めての解ではありませんが、プログラミングアルゴリズムではDPだけが唯一で、残りの0/6の様子が好きではないので、今日は2つの問題を解決しました.そのうちの1つを位置づけたいと思います.
質問リンク
12=(55+5)/5などN,numberが与えられると,Nを利用してnumberを表すだけで,その中で最も少ないNを見つければよい.
最初は1から与えられた数字までbottom-upで解決したいと思っていました.iを表現するために、先に求めた記憶[1~i-1]の内容を利用して最大値を求めるように求めた記憶[i]は、再びi+1を求める形で解決しようと試みる!
結果は間違っていた!
私の薄っぺらなDP知識に依存しているからか、このbottom-up方式は答えに指定されていて、規則性を発見するためにあちこち書いても、特別な法則が分からないのに、どうしてだめなのか、他の方法を試してみなかった.
最終的にはブログ記事を参考にして、新しい方法でアクセスして解決することができます.
通る解答の核心の概念は想像するより簡単です
与えられた整数Nは集合(i)と呼ばれ、集合(n)が作成されたときに用いられる.セット(n-1)&セット(1) セット(n-2)&セット(2) セット(n-3)&セット(3)
... セット(1)&セット(n-1) これはn個を用いてn個の数の集合を作成し,集合(n)を完成させる方式である.
ここには余計な配慮が必要なやつがいて、N羅列のN N Nと同じ形式の整数です.
説明が抽象的に見えるので、具体的な例で説明しましょう.
N=2ならnumber=11!2を使用して整数を作成できます: 2つの2で作成できる整数:2+2、(2-2)、2*2、2/2、22
この場合、2-2=0で、私たちが探している数字は1以上32000以下の整数で、除外できます!
すなわち、2つの2を用いる生成可能な整数は、22、4、1の3種類: である.
3つの2を使用して作成できる数 加算)2+222+4,2+1,(22+2,22+4,22+1) マイナス記号)2-22、2-4、2-1、22-2、4-2、1-2 積)222、24、21、(222、42、12) .除算)2/22、2/4、2/1、22/2、4/2、2/1 そして222! しかし乗算と加算の交換法則は成立するので、同じ演算結果が2回出ます!括弧の中の数字は計算しないでください!
また、減算については、演算結果が1未満であれば、それを排除することができ、除算演算時に除算が0のエラーが発生することを回避することができる.
このようにして1から8方向に2次元ベクトルを完成させ、計算結果がnumberの場合、検索を停止し、正しい答えを返すようにコードを記述します.
延び延びになっていたDPが今日やっと始まりました
初めての解ではありませんが、プログラミングアルゴリズムではDPだけが唯一で、残りの0/6の様子が好きではないので、今日は2つの問題を解決しました.そのうちの1つを位置づけたいと思います.
プログラマNとして表す
質問リンク
12=(55+5)/5などN,numberが与えられると,Nを利用してnumberを表すだけで,その中で最も少ないNを見つければよい.
制限とI/O
私の答え
最初は1から与えられた数字までbottom-upで解決したいと思っていました.iを表現するために、先に求めた記憶[1~i-1]の内容を利用して最大値を求めるように求めた記憶[i]は、再びi+1を求める形で解決しようと試みる!
結果は間違っていた!
私の薄っぺらなDP知識に依存しているからか、このbottom-up方式は答えに指定されていて、規則性を発見するためにあちこち書いても、特別な法則が分からないのに、どうしてだめなのか、他の方法を試してみなかった.
最終的にはブログ記事を参考にして、新しい方法でアクセスして解決することができます.
ソリューション
通る解答の核心の概念は想像するより簡単です
与えられた整数Nは集合(i)と呼ばれ、集合(n)が作成されたときに用いられる.
...
ここには余計な配慮が必要なやつがいて、N羅列のN N Nと同じ形式の整数です.
説明が抽象的に見えるので、具体的な例で説明しましょう.
N=2ならnumber=11!
この場合、2-2=0で、私たちが探している数字は1以上32000以下の整数で、除外できます!
すなわち、2つの2を用いる生成可能な整数は、22、4、1の3種類:
3つの
また、減算については、演算結果が1未満であれば、それを排除することができ、除算演算時に除算が0のエラーが発生することを回避することができる.
このようにして1から8方向に2次元ベクトルを完成させ、計算結果がnumberの場合、検索を停止し、正しい答えを返すようにコードを記述します.
コード#コード#
#include <vector>
#include <algorithm>
using namespace std;
// N을 times 번 이어붙이 수 반환
int getConnectedNumber(int N, int times){
int ans = 0;
for (int i = 0; i < times-1; ++i) {
ans *= 10;
ans += (N * 10);
}
ans += N;
return ans;
}
// 사칙 연산을 통해 만들 수 있는 수 추가, number 인지 확인하면 반환
bool basicOperating(vector<vector<int>> & sets, int a, int b, int number){
int n = a+b;
for (int i = 0; i < sets[a].size(); ++i) {
for (int j = 0; j < sets[b].size(); ++j) {
int subtract, divide, sum, multiple;
subtract = sets[a][i] - sets[b][j];
divide = sets[a][i] / sets[b][j];
// 뺀 값과 나눈 값은 1 이상일 때에만 적용
if (subtract >= 1) sets[n].push_back(subtract);
if (divide >= 1) sets[n].push_back(divide);
if (a >= b) {
sum = sets[a][i] + sets[b][j];
multiple = sets[a][i] * sets[b][j];
sets[n].push_back(sum);
sets[n].push_back(multiple);
}
// 찾던 수라면 탐색 중단하고 반환
if (subtract == number || divide == number || sum == number || multiple == number) return true;
}
}
return false;
}
int solution(int N, int number) {
int answer = 0;
bool found = false;
vector<vector<int>> numsUsingN(9);
vector<int> base = {N, N*10 + N, N+N, N*N, N/N};
if (base[0] == number) return 1;
numsUsingN[1].push_back(N);
for (int i = 1; i < base.size() ; ++i) {
if (base[i] == number) return 2;
numsUsingN[2].push_back(base[i]);
}
numsUsingN[2].erase(unique(numsUsingN[2].begin(), numsUsingN[2].end()), numsUsingN[2].end());
for (int i = 3; i <= 8 ; ++i) {
int connected = getConnectedNumber(N, i);
if (connected == number) {
found = true;
break;
}else{
numsUsingN[i].push_back(connected);
}
for (int j = i-1; j >= 1 ; j--) {
if (basicOperating(numsUsingN, j, i-j, number)){
answer = i;
found = true;
break;
}
}
if (found) break;
}
if (!found) answer = -1;
return answer;
}
参考資料Reference
この問題について([解析アルゴリズムプール]Programmers Nとして表示), 我々は、より多くの情報をここで見つけました https://velog.io/@nnnyeong/알고리즘-풀이-분석-Programmers-N으로-표현テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol