输入包含多组测试数据。 每组测试数据由两行组成。第一行是序列的长度N (1 <= N <= 1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000(可能重复)。
对于每组测试数据,输出其最大上升子序列和。
7 1 7 3 5 9 4 8
18
#include<bits/stdc++.h> using namespace std; const int maxn=1000; int a[maxn]; int dp[maxn];//dp[i]表示以i标号为末尾的上升子序列的和 int main(){ int k; while(cin>>k){ for(int i=0;i<k;i++){ cin>>a[i]; } int ans=0; for(int i=0;i<k;i++){ dp[i]=a[i]; for(int j=0;j<i;j++){ if(a[j]<a[i]){ dp[i]=max(dp[i],dp[j]+a[i]); } } ans=max(ans,dp[i]); } cout<<ans<<endl; } return 0; }
#include<stdio.h> int max(int x,int y); int main() { int n; while(scanf("%d",&n) != EOF) { int i,j,ans = 0; int num[n],dp[1000]; for(i = 0;i < n;i++) scanf("%d",&num[i]); for(i = 0;i < n;i++) { dp[i] = num[i]; } for(i = 1;i < n;i++) { for(j = 0;j < i;j++) { if(num[j] < num[i]) { dp[i] = max(dp[j] + num[i],dp[i]); } } if(dp[i] > ans) { ans = dp[i]; } } printf("%d\n",ans); } } int max(int x,int y) { if(x > y) return x; return y; }
// 最长上升 和 上升子序列最大和 不一样 #include <bits/stdc++.h> using namespace std; const int AX = 1e3 + 66 ; int dp[AX]; int a[AX] ; int n ; int main() { while( ~scanf("%d",&n) ) { for( int i = 0 ; i < n ; i++ ) { scanf("%d",&a[i]); } dp[0] = a[0] ; int tot = 0 ; int id ; for( int i = 1 ; i < n ; i++ ) { dp[i] = a[i] ; for( int j = 0 ; j < i ; j++ ) { if( a[j] < a[i] ) { if( dp[i] < dp[j] + a[i] ) { dp[i] = dp[j] + a[i] ; } } } tot = max( tot , dp[i] ); } printf("%d\n",tot); } return 0 ; }
#include <stdio.h> (737)#include <stdint.h> /* 最长上升子序列和 在所有的上升子序列中,找到最大的子序列的和 我们只需要记录,以 i 位置结束的位置, 所形成的最长子序列的和 input: 7 1 7 3 5 9 4 8 iuput: 18 */ #define N 1010 int arr[N]; int dp[N]; // 最长递增子序列 int max(int a, int b) { return a > b ? a : b; } int main() { // freopen("data.txt", "r", stdin); int n; while (scanf("%d", &n) != EOF) { for (int i = 0; i < n; i++) { scanf("%d", &arr[i]); } int maxVal = 0; for (int i = 0; i < n; i++) { dp[i] = arr[i]; for (int j = 0; j < i; j++) { if (arr[i] > arr[j]) { // 满足递增的子序列, 记录下 dp[i] 是子序列的和 dp[i] = max(dp[i], dp[j] + arr[i]); if (dp[i] > maxVal) { maxVal = dp[i]; } } } } printf("%d\n", maxVal); } return 0; }
n = int(input()) arr = list(map(int,input().split())) res = [] for k in range(n): res.append(arr[k]) for i in range(1,n): for j in range(i-1,-1,-1): if arr[j]<arr[i]: res[i] = max(res[i],arr[i]+res[j]) print(max(res))
#include<stdio.h> int main() { int n,i,j; scanf("%d",&n); int num[n],sum[n]; for(i=0;i<=n-1;i++) { scanf("%d",&num[i]); sum[i]=num[i]; } int max=num[0]; for(i=1;i<=n-1;i++) { for(j=0;j<=i-1;j++) { if(num[i]>num[j]) { if(num[i]+sum[j]>sum[i]) { sum[i]=num[i]+sum[j]; } } } } for(i=0;i<=n-1;i++) { if(max<sum[i]) max=sum[i]; } printf("%d",max); return 0; }
动态规划问题 import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); while(in.hasNext()){ int n = in.nextInt(); int[] arr = new int[n]; int[] dp = new int[n]; for(int i=0;i<n;i++){ arr[i] = in.nextInt(); dp[i] = arr[i]; } for(int i=1;i<n;i++){ for(int j=i-1;j>=0;j--){ if(arr[i]>arr[j]) dp[i] = Math.max(dp[i], arr[i]+dp[j]); } } int max= dp[0]; for(int i=1;i<n;i++) max = Math.max(max,dp[i]); System.out.println(max); } } }
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn = 1001; int num[maxn]; int mymax[maxn]; // mymax[i] 表示 以 num[i] 结尾的子序列的最大值 int main() { int n; while(cin >> n) { memset(mymax, 0, sizeof(mymax)); for(int i = 0; i < n; ++i) { cin >> num[i]; } int max = num[0]; for(int i = 0; i < n; ++i) { mymax[i] = num[i]; for(int j = 0; j < i; ++j) { if(num[j] < num[i] && mymax[j]+num[i] > mymax[i]) { mymax[i] = mymax[j]+num[i]; } } if(mymax[i] > max) { max = mymax[i]; } } cout << max << endl; } return 0; }
#include<iostream> #include<algorithm> using namespace std; int main(){ int num[1001]; int sum[1001]; int n; while(cin>>n){ for(int i=0;i<n;i++){ cin>>num[i]; sum[i] = num[i]; } for(int i=1;i<n;i++){ for(int j=i-1;j>=0;--j){ if(num[j]<num[i]){ sum[i] = max(sum[i],sum[j]+num[i]); } } } int max = 0; for(int i=0;i<n;i++){ if(sum[i]>max) max = sum[i]; } cout<<max<<endl; } return 0; }
//还是动态规划,在上一题的基础上进行改进。注意是严格单调递增 #include<stdio.h> #include<vector> #include<algorithm> using namespace std; int main(){ int k; while(scanf("%d",&k)!=EOF){ vector<int> height(k,0); for(int i=0;i<k;i++){ scanf("%d",&height[i]); } vector<int> dp(k); for(int i=0;i<k;i++){ dp[i]=height[i]; } int maxVal=height[0]; for(int i=1;i<k;i++){ int temp=0; for(int j=i;j>0;j--){ if(height[i]>height[i-j]){ temp=max(temp,dp[i-j]); } } dp[i]=dp[i]+temp; if(maxVal<dp[i]){ maxVal=dp[i]; } } printf("%d\n",maxVal); } }
动态规划求解
开始假设所有的数自成最大递增子序列,也就是sum[i]=num[i];
后面再从前向后遍历,如果前面某个数小于当前的数,那么那个数的最大递增子序列的和加上当前的数会构成更大的递增子序列和,找出所有这样的和的最大值作为以当前数为尾的最大递增子序列的和。
#include <iostream>
using namespace std;
int main()
{
int n;
int num[1001];
int sum[1001];
while(cin>>n)
{
int tmpsum = 0, maxsum = 0;
for(int i = 0; i<n; i++)
{
cin>>num[i];
sum[i] = num[i]; //初始化,所有数自成一个最大递增子序列
}
sum[0] = num[0];
for(int i = 1; i<n; i++)
{
for(int j = i-1; j>=0; j--)
{
if(num[j]<num[i]) //符合递增子序列
sum[i] = max(sum[j]+num[i], sum[i]);
}
}
maxsum = sum[0];
for(int i = 1; i<n; i++)
{
if(maxsum<sum[i]) maxsum = sum[i];
}
cout<<maxsum<<endl;
}
return 0;
}
/* 动态规划,是最长递增子序列的一个变形 dp[i] 表示以a[i]为结尾的最长递增子序列的和 1.如果a[i]之前的都比a[i]大,那么和就为自身的大小 2.如果a[i]之前有比它小的a[j],那么就将a[i]添加到 以a[j]为结尾的序列的末尾,这样就是a[i]的最长公共子序列和 */ #include <bits/stdc++.h> using namespace std; const int maxn = 1010; int dp[maxn]; int arr[maxn]; int main() { int n; while(~scanf("%d",&n)) { for(int i=0; i<n; i++) { // input scanf("%d",&arr[i]); dp[i] = arr[i]; // 默认所有数自己本身是一个递增序列 } int ans = INT_MIN; for(int i=0; i<n; i++) { for(int j=0; j<i; j++) { // 找在i之前有没有比i小的 if(arr[j]<arr[i]) { dp[i] = max(dp[j]+arr[i],dp[i]); } ans = max(ans,dp[i]); } } printf("%d\n",ans); } }
#include <iostream> #include<vector> #include<algorithm> using namespace std; int main() { int n; while(cin>>n){ vector<int> b(n); for(int i=0;i<n;i++){ cin>>b[i]; } vector<int> dp(n); dp[0] = b[0]; for(int i=1;i<n;i++){ dp[i] = b[i]; for(int j=0;j<i;j++){ if(b[i]>b[j]) dp[i] = max(dp[i],dp[j]+b[i]); } } cout<<*max_element(dp.begin(),dp.end())<<endl; } return 0; }