這道題首先要對輸入進行處理,解題的一般思路是將所給的c數組與r數組按照各個歷史事件的rank重排,即最早的事件的編號放在數組的第一位......然後這題轉化為求兩個串的最長公共子序列長度的問題。
但我使用了另外一種解法(雖然仍然要用動態規劃 =-= ):
只對輸入的c數組重排(即c數組中c[i]存放rank為i的事件的編號),r數組不變。建立ans數組,ans[i]存放以rank為i為結尾的最長序列長度,初始化均為1。
程序從第0個開始填充ans數組。當執行到求ans[i]時,分別判斷rank從0 — i-1 的事件,如j事件,在學生的解答(即r數組中數據)中發生時間是否也在i事件之前,如果在其之前,則用ans[j]+1更新ans[i](因為ans[i]初始化為1)。ans數組填充完畢後,其中最大值即為所求結果。
我的代碼如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <string>
#include <algorithm>
using namespace std;
int c[20],r[20];
int ans[20];
int N;
int main()
{
cin >> N;
int ci;
for(int i=0; i<N; i++)
{//按時間順序重排c數組
cin >> ci;
c[ci-1]=i;
}
int tmp;
while(cin >> tmp)
{
r[0]=tmp;
ans[tmp]=0;
for(int i=1; i<N; i++)
cin >> r[i];
int maxlen=1;
ans[0]=1;
for(int i=1; i<N; i++)
{
ans[i]=1;
//依次判斷事件0~i-1
for(int j=0; j<i; j++)
{
if(r[c[j]] < r[c[i]]) { if(ans[i]<(ans[j]+1)) ans[i]=ans[j]+1; }
}
if(maxlen<ans[i]) maxlen=ans[i];
}
cout << maxlen << endl;
}
return 0;
}