N개의 다른 유형의 스티커가 있다고 가정합니다. 스티커의 각 유형에는 소문자 영어 단어가 있습니다. 우리는 스티커 컬렉션에서 개별 문자를 잘라내어 재배열하여 지정된 대상 문자열을 철자하고 싶습니다. 필요한 경우 각 스티커를 한 번 이상 사용할 수 있으며 각 스티커의 수량은 무한합니다.
우리는 대상을 철자하는 데 필요한 최소한의 스티커를 찾아야만 합니까? 작업이 불가능한 경우 -1을 반환합니다.
따라서 입력이 ["dog", "sentence", "antenna"]이고 대상이 "dance"인 경우 답은 3
이 됩니다.이 문제를 해결하기 위해 다음 단계를 따릅니다. −
- n :=대상 크기
- N :=1을 왼쪽으로 n번 이동
- 크기 N의 배열 dp를 정의하고 inf로 초기화
- dp[0] :=0
- 초기화 i의 경우:=0, i
- dp[i]가 inf와 같으면 -
- 다음 부분은 무시하고 다음 반복으로 건너뜁니다.
- j 초기화의 경우:=0, j <스티커 크기, 업데이트(j를 1만큼 증가), 수행 -
- :=스티커[j]
- x :=나
- 초기화 k의 경우:=0, k
- z :=s[k]
- 초기화 l :=0의 경우, l <타겟의 크기일 때 업데이트(l을 1씩 증가), 수행 -
- target[l]이 z와 동일하고 (오른쪽 시프트 x, l 비트) AND 1)이 0과 같으면 -
- x :=x OR (왼쪽 l비트로 1 이동)
- 루프에서 빠져나오기
- dp[x] :=dp[x] 및 dp[i] + 1의 최소값
- dp[i]가 inf와 같으면 -
이해를 돕기 위해 다음 구현을 살펴보겠습니다. −
예
#include <bits/stdc++.h> using namespace std; class Solution { public: int minStickers(vector<string>& stickers, string target) { int n = target.size(); int N = 1 << n; vector <int> dp(N, INT_MAX); dp[0] = 0; for(int i = 0; i < N; i++){ if(dp[i] == INT_MAX) continue; for(int j = 0; j < stickers.size(); j++){ string s = stickers[j]; int x = i; for(int k = 0; k < s.size(); k++){ char z = s[k]; for(int l = 0; l < target.size(); l++){ if(target[l] == z && ((x >> l) & 1) == 0){ x |= (1 << l); break; } } } dp[x] = min(dp[x], dp[i] + 1); } } return dp[N - 1] == INT_MAX? -1 : dp[N - 1]; } }; main(){ Solution ob; vector<string> v = {"dog", "sentence","antenna"}; cout << (ob.minStickers(v, "dance")); }
입력
["dog", "sentence","antenna"] "dance"
출력
3