出自一次很失敗的開學測試
LIS自然會做
可以參見:https://blog.csdn.net/Radium_1209/article/details/79704234
由于對于LIS的nlogn算法不熟悉,導致錯誤理解,記錄的路徑出現了問題,其中還用了n^2的算法記錄路徑(好理解),但是不出所料T了。
正確的方法應該是:由于nlogn算法中,dp[i]存的是長度為i的最后一位數字,并不是路徑!!!我們可以用一個path數組來標記每一個數字位于的位置,然后通過dfs倒著來找最后結果長度的最后一個,或者不用dfs直接找也行。
?
例題:(UVA481)
Write a program that will select the longest?strictly?increasing subsequence from a sequence of integers.
Input
The input file will contain a sequence of integers (positive, negative, and/or zero). Each line of the input file will contain one integer.
Output
The output for this program will be a line indicating the length of the longest subsequence, a?newline, a dash character ('-'), a?newline, and then the subsequence itself printed with one integer per line. If the input contains more than one longest subsequence, the output file should print the one that occurs last in the input file.
Notice that the second 8 was not included -- the subsequence must be strictly increasing.
Sample Input
-7 10 9 2 3 8 8 1
Sample Output
4 - -7 2 3 8
題意:求LIS并輸出路徑(最后一個)
dfs版:
#include <cstdio>
#include <iostream>
using namespace std;int n=1,a[1000005];
int dp[1000005];
int path[1000005];void dfs(int i,int x)
{if (i<1 || x<=0)return;while(path[i]!=x)i--;dfs(i,x-1);printf("%d\n",a[i]);
}int main()
{while(~scanf("%d",&a[n])){n++;}n--;int len=1;dp[1]=a[1]; path[1]=1;for (int i=2;i<=n;i++){if (a[i]>dp[len]){dp[++len]=a[i];path[i]=len;}else{int pos=lower_bound(dp+1,dp+len+1,a[i])-dp;dp[pos]=a[i];path[i]=pos;}}printf("%d\n-\n",len);dfs(n,len);return 0;
}
?
非dfs版:
#include <cstdio>
#include <iostream>
using namespace std;int n=1,a[1000005];
int dp[1000005];
int path[1000005];
int ans[1000005];int main()
{while(~scanf("%d",&a[n])){n++;}n--;int len=1;dp[1]=a[1]; path[1]=1;for (int i=2;i<=n;i++){if (a[i]>dp[len]){dp[++len]=a[i];path[i]=len;}else{int pos=lower_bound(dp+1,dp+len+1,a[i])-dp;dp[pos]=a[i];path[i]=pos;}}printf("%d\n-\n",len);int temp=n;int l=len;while(l>=1){int i;for(i=temp;i>=1;i--){if (path[i]==l){ans[l]=a[i];l--; temp=i;break;}}if (i==0)break;}for (int i=1;i<=len;i++)printf("%d\n",ans[i]);return 0;
}
?
n^2版本(T了,正確性未知)
#include <cstdio>
#include <iostream>
using namespace std;int n=1,a[1000005];
int dp[1000005];
int path[1000005];
int ans[1000005];int main()
{while(~scanf("%d",&a[n])){n++;}n--;int len=0;for (int i=1;i<=n;i++){dp[i]=1;for (int j=1;j<i;j++)if (a[j]<a[i]){if (dp[i]<dp[j]+1){dp[i]=dp[j]+1;path[dp[i]]=j;}}if (dp[i]>=len){len=dp[i];ans[len]=a[i];for (int i=len;i>=2;i--)ans[i-1]=a[path[i]];}}printf("%d\n-\n",len);for (int i=1;i<=len;i++)printf("%d\n",ans[i]);return 0;
}
?