동적 계획 - 하위 시퀀스 수
제목 상세 정보: 하위 서열의 정의: 하나의 서열에 대한 a=a[1], a[2],......a[n], 비공식 서열 a'=a[p1], a[p2]......a[pm]는 a의 하위 서열로 그 중 1<=p1
입력: 길이가 n인 수조 1<=n<=100, 수조 원소 0<=a[i]<=110
출력: 하위 서열의 개수가 1000000007에 대한 나머지 결과를 얻습니다. (답이 비교적 크기 때문에 Mod 1000000007의 결과를 출력하면 됩니다.)
함수 헤더: C/C++: int run (cons int *a, int n);java public static int run(int [] a);
이 문제도 나를 오랫동안 괴롭혔지만 좋은 방법을 찾지 못했다. 이 문제는 동적 기획으로 풀 수 있을 것이다. 그래서 나도 동적 기획의 사상을 배우고 연습 문제를 찾아냈다. 그러나 이 상태의 전환 방정식은 나를 견디기 어렵다. 원래 수학의 기초가 보통이어서 더욱 난이도가 높아졌다.비록 내가 최종적으로 이 문제를 해결했지만 그것은 대신의 지시를 받은 상황에서 만들어진 것이다. 나는 여기서 단지 문제를 풀고 쓴 김에 결점을 보완하고 자신의 이해가 정확한지 보려고 한다. 사실은 하고 싶은 것과 하는 것은 별개의 일이니 여러분도 바로잡아 주십시오.
문제 풀이:
서열의 전 k개수의 서열 개수가 d(k)라고 가정하면 전 k-1 서열의 개수는 d(k-1) 서열이다. k-1에서 k로의 변화는 어떠한가?
1. 수조 a[N]의 k번째 수가 a[k]라고 가정하고 a[k]가 앞의 k-1개수와 같지 않으면 d(k)=d(k-1)+[d(k-1)+1]=2d(k-1)+1이 있는데 왜 그럴까요?이렇게 생각할 수 있다. 앞의 k-1항의 서열 개수는 d(k-1)이다. 그 앞의 k개수는 앞의 k-1항의 토대 위에서 하나의 수 a[k](a[k]와 앞의 k-1개의 수가 임의로 같다). 그러면 원래의 조합에 a[k]를 더하면 d(k-1)개가 있고 또 하나의 a[k]가 스스로 서열을 구성하기 때문에 1을 추가해야 한다.
2. a[k]가 앞의 k-1개수 중 하나와 같다고 가정하면 앞의 k-1 하위 서열 개수 d(k-1)를 더한다. 그러나 앞에 a[k]와 같은 수가 있기 때문에 중복된 부분을 빼고 중복된 부분을 어떻게 찾을까. k에서 가장 가까운 a[k]와 같은 수가 첫 번째 a[t]=a[k], 즉 서열(a[1], a[2],a[2],...,a[k-1],a[k],a],a[k]],a[k]]],a[k]]]],a[k][k]][k]]]].우리는 이미 서열(a[1], a[2],......, a[t])의 서열 개수가 d(t)라는 것을 알고 있다. 그러면 d(t-1)는 중복된 부분이다. 여기는 스스로 생각을 잘 해야 하고 알고리즘의 관건적인 부분이다. 여기서 내가 설명하고자 하는 것은 왜 k에서 가장 가까운 t를 찾아서 a[t]=a[k]를 만들 수 있느냐는 것이다.설명은 다음과 같다. 우리는 1-n에서 수조를 두루 훑어보았고 d(i)를 계산하는 i는 1에서 n까지 순서대로 계산했다. 그러면 a[k]=a[t]를 처음 만났을 때 조건을 충족시켰다. 그리고 단 하나의 t만 a[t]=a[k]를 만들었다. 예를 들어 서열(1, 2, 3, 2, 4, 2)을 각각 d(1), d(2), d(3), d(4), d(5), d(6)를 계산했다.우리는 d(4)를 계산할 때 a[4]=a[2](하표가 1부터 시작한다고 가정)를 발견했기 때문에 d(4)=2*d(3)-d(2-1)=2d(3)-d(1)를 발견했다.d(6)를 계산할 때도 a[6]=a[4]=a[2]가 있지만 우리 앞에 a[2]가 중복된 부분을 줄였기 때문에 더 이상 줄일 필요가 없다. d(6)=2*d(5)-d(4-1)=2d(5)-d(3).
과정이 번거로우니 결론을 총괄해 보겠습니다.
상태 전환 방정식은 다음과 같습니다.
d(k) = 2 * d(k - 1) + 1; a[k] != a[i],i = 1,2,3……k - 1;
d(k) = 2 * d(k - 1) - d(t - 1); k에서 검색하면 k에서 가장 가까운 t가 존재하여 a[t]=a[k].
상태 전이 방정식을 분석하면 나머지는 기본적으로 식은 죽 먹기입니다. 코드는 다음과 같습니다.
/*
: : a=a[1],a[2],......a[n],
a'=a[p1],a[p2]......a[pm] a , 1<=p1<p2<.....<pm<=n。
:4,14,2,3 14,1,2,3 4,13,14,1,2,3 。 a, ,
1 , a 。 : n 1<=n<=100, 0<=a[i]<=110
: 1000000007 ( , Mod 1000000007 )。
: C/C++: int run(cons int *a,int n); java public static int run(int [] a);
*/
#include <stdio.h>
#include <stdlib.h>
#define M 1000000007
int run(const int *a,int n)
{
long long SubArray[120] = {0};
int LastIndex[120] = {0};
int iter = 0;
for(iter = 1; iter <= n; iter++)
{
switch(LastIndex[a[iter - 1]])
{
case 0:
{
SubArray[iter] = (2 * SubArray[iter - 1] + 1) % M;
break;
}
default:
{
SubArray[iter] = (2 * SubArray[iter - 1] - SubArray[LastIndex[a[iter - 1]] - 1] + M) % M;
break;
}
}
LastIndex[a[iter - 1]] = iter;
}
return SubArray[n] % M;
}
int main(void)
{
//int a[5] = {1, 2, 2, 3 ,3};
int a[4] = {1, 2, 3 , 2};
printf("the result is %d
", run(a, 4));
return 0;
}
참고: 이 블로그는 블로그 텃밭의 블로그와 동일한 블로그 소유자입니다.http://www.cnblogs.com/bestDavid/
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【경쟁 프로 전형적인 90문】008의 해설(python)의 해설 기사입니다. 해설의 이미지를 봐도 모르는 (이해력이 부족한) 것이 많이 있었으므로, 나중에 다시 풀었을 때에 확인할 수 있도록 정리했습니다. ※순차적으로, 모든 문제의 해설 기사를 들어갈 예정입니다. 문자열...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.