1. 程式人生 > >XDU1131 思維+dp優化

XDU1131 思維+dp優化

很多 get mic sof ron .cn map 復雜度 class

題意

分析

一個直觀的做法是,枚舉前兩項,不斷檢查前一項,這需要維護一個有序數組並且帶下標(可以用一個map<int,vector<int> >,將數字相同的數推倒一個vector中,vector中存的就是相同的數的位置)

時間復雜度:O(n^2*(logn+logn))

這個做法不太行啊,兩個log,有點卡不過去

由於有很多重復的枚舉,dp優化

dp[i][j]:以i,j為開始兩個的最大長度

轉移:顯然需要k且k>j的help, a[k]=a[i]+a[j] (k>j)即可(二分即可)

另一種dp[i][j]:以i,j為結束兩個的最大長度

轉移:需要k且k<i的help ,a[k]+a[i]==a[j](k<i)

但這個狀態不太好找二分不好check

時間復雜度O(n^2*logn)

技術分享圖片
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <iostream>
#include <cmath>
#include <queue>
#include <ctime>
using namespace std;
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
#define
dbg(x) cout<<#x<<" = "<< (x)<< endl #define pb push_back #define fi first #define se second #define ll long long #define sz(x) (int)(x).size() #define pll pair<long long,long long> #define pii pair<int,int> #define pq priority_queue vector<pll> v; int dp[1010
][1010]; ll a[1010]; int main(){ int n; while(scanf("%d",&n)!=EOF){ v.clear(); for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); v.pb({a[i],i}); } if(n==1){ printf("1\n%lld\n",a[1]); continue; } sort(v.begin(),v.end()); pll res;int cnt=0; for(int i=n-1;i>=1;i--){ for(int j=i+1;j<=n;j++){ auto it=lower_bound(v.begin(),v.end(),(pll){a[i]+a[j],j+1}); if(it!=v.end() && it->fi==a[i]+a[j]){ dp[i][j]=dp[j][it->se]+1; }else{ dp[i][j]=2; } if(dp[i][j]>cnt || (dp[i][j]==cnt && (pll){a[i],a[j]}<res)){ res={a[i],a[j]}; cnt=dp[i][j]; } } } printf("%d\n",cnt); printf("%lld %lld",res.fi,res.se); for(int i=2;i<cnt;i++){ printf(" %lld",res.fi+res.se); res.fi+=res.se; swap(res.fi,res.se); } printf("\n"); } return 0; }
View Code

XDU1131 思維+dp優化