dp practice 1

https://codeforces.com/problemset/problem/553/A

dp+组合数学

dp[i] 放前i种颜色的方法数

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3+7;
const ll mod = 1e9+7;
int a[N];
ll dp[N],f[N];
void work(){
    f[0]=1;
    f[1]=1;
    for(int i=2;i<N;i++)
        f[i]=f[i-1]*i%mod;
}
ll q_pow(ll a,ll n){
    ll ans=1; ll base=a;
    while(n){
        if(n&1) ans=(ans*base)%mod;
        base=base*base%mod;
        n>>=1;
    }
        return ans;
}
ll inv(ll a,ll b){
    return q_pow(a,b-2);
} 
ll C(int n,int m){
    return f[n]*inv(f[n-m]*f[m]%mod,mod)%mod;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    int k; cin>>k;
    for(int i=1;i<=k;i++){
        cin>>a[i];    
    }
    work();
    int sum=a[1];
    dp[1]=1;
    for(int i=2;i<=k;i++){
        dp[i]=(dp[i-1]*C(sum+a[i]-1,a[i]-1))%mod;
        sum+=a[i];
    }
    cout<<dp[k]<<endl;
    return 0;
}
View Code

https://codeforces.com/problemset/problem/264/B

dp+简单数论

dp[i] 表示当前当前位置因子为i的所能构成的序列长度

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+7;
const ll mod = 1e9+7;
int a[N];
int dp[N];
vector<int> v[N];
void work(){
    for(int i=2;i<N;i++)
        for(int j=i;j<N;j+=i)
            v[j].push_back(i);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    int n; cin>>n;
    work();
    for(int i=1;i<=n;i++) cin>>a[i];
    v[1].push_back(1);
    for(int i=1;i<=n;i++){
        int tmp=0;
        for(int j=0;j<v[a[i]].size();j++)
            tmp=max(tmp,dp[v[a[i]][j]]);
        for(int j=0;j<v[a[i]].size();j++)
            dp[v[a[i]][j]]=tmp+1;
    }
    int ans=0;
    for(int i=1;i<N;i++) ans=max(ans,dp[i]);
    cout<<ans<<endl; 
    return 0;
}
View Code

 http://codeforces.com/contest/339/problem/C

dp+路径还原

dp[i][j] 表示用了j克的砝码 变成了重量为i 是否存在

#include <bits/stdc++.h>
using namespace std;
const double pi = acos(-1.0);
const int N = 2e5+7;
const int inf = 0x3f3f3f3f;
const double eps = 1e-6;
typedef long long ll;
typedef pair<int,int> pii;
const ll mod = 1e9+7;
vector<int> w;
int dp[207][15];
pii path[1007][207][15];
void find(int x,int y,int cnt){
    if(cnt==0) return ;
    find(path[cnt][x][y].first,path[cnt][x][y].second,cnt-1);
    cout<<y<<" ";
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    string s; cin>>s;
    for(int i=0;i<10;i++) if(s[i]=='1') w.push_back(i+1);
    int m; cin>>m;
    int fix=100;
    for(int i=0;i<w.size();i++){
        dp[fix+w[i]][w[i]]=1;
        path[1][fix+w[i]][w[i]]=make_pair(fix,0);
    }
    for(int i=2;i<=m;i++){
        if(i&1){
            for(int j=fix-50;j<fix;j++)
                for(int k=0;k<w.size();k++)
                    if(dp[j][w[k]]){
//                        cout<<j<<" "<<w[k]<<endl;
                        for(int l=0;l<w.size();l++){
//                            cout<<j<<" "<<fix<<endl; 
                            if(w[l]==w[k]||j+w[l]<=fix) continue;
                            dp[j+w[l]][w[l]]=1;
                            path[i][j+w[l]][w[l]]=make_pair(j,w[k]); 
                        }
                        dp[j][w[k]]=0;
                    }
        }else{
        //    cout<<"11"<<endl;
            for(int j=fix+1;j<=fix+1+50;j++)
                for(int k=0;k<w.size();k++)
                    if(dp[j][w[k]]){
                    //    cout<<j<<" "<<w[k]<<endl;
                        for(int l=0;l<w.size();l++){
                            if(w[l]==w[k]||j-w[l]>=fix) continue;
                            dp[j-w[l]][w[l]]=1;
                        //    cout<<j-w[l]<<endl;
                            path[i][j-w[l]][w[l]]=make_pair(j,w[k]);
                        }
                        dp[j][w[k]]=0;
                    }
        }
    }
    if(m&1){
        int x=-1,y=-1;
        for(int i=fix+1;i<fix+1+50;i++)
            for(int j=0;j<w.size();j++)
                if(dp[i][w[j]]){
                    x=i; y=w[j];
                    break;
                }
        if(x==-1){
            cout<<"NO
";
        }else{
            cout<<"YES
";
//            cout<<x<<" "<<y<<endl;
            find(x,y,m);
            cout<<"
";
        }
    }else{
        int x=-1,y=-1;
        for(int i=fix-50;i<fix;i++)
            for(int j=0;j<w.size();j++)
                if(dp[i][w[j]]){
                    x=i; y=w[j];
                    break;
                }
        if(x==-1){
            cout<<"NO
";
        }else{
            cout<<"YES
";
//            cout<<x<<" "<<y<<endl;
            find(x,y,m);
            cout<<"
";
        }
    }
    return 0;
}
View Code

 https://codeforces.com/problemset/problem/977/F

dp+路径

dp[i]表示以i位置为结尾所能构成的最大连续个数 用一个map记录最后一个数为i的最大长度

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
const int N = 2e5+7;
const ll mod = 1e9+7;
int a[N],dp[N],path[N];
map<int,pi> mm;
vector<int> v;
void find(int x){
    if(!x) return ;
    find(path[x]);
    v.push_back(x);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    int n; cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    for(int i=1;i<=n;i++){
        if(mm.count(a[i]-1)){
            dp[i]=mm[a[i]-1].first+1;
            mm[a[i]]=make_pair(dp[i],i);
            path[i]=mm[a[i]-1].second;
        }else{
            dp[i]=1;
            mm[a[i]]=make_pair(1,i);
        }
    }
    int ans=0; int xx;
    for(int i=1;i<=n;i++){
        if(dp[i]>ans){
            ans=dp[i];
            xx=i;
        }
    }
    find(xx);
    cout<<ans<<"
";
    for(int i=0;i<v.size();i++)
        cout<<v[i]<<" ";
    cout<<"
";
    return 0;
}
View Code

 https://codeforces.com/problemset/problem/711/C

dp[i][j][k] 表示前i个位置 最后一个数颜色为j 且分为k组的最小花费

#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const double eps = 1e-6;
const int N = 4e5+7;
typedef long long ll;
const ll mod = 1e9+7;
using namespace std;
int a[107];
ll cost[107][107];
ll dp[107][107][107];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    int n,m,k; cin>>n>>m>>k;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>cost[i][j];
    memset(dp,0x3f3f3f3f3f3f3f3f,sizeof(dp));
    for(int i=1;i<=n;i++){
        for(int kk=1;kk<=k;kk++){
            if(kk>i) break;
            if(a[i]){
                if(i==1){
                    dp[i][a[i]][1]=0;
                    continue;
                }
                dp[i][a[i]][kk]=dp[i-1][a[i]][kk];
                for(int j=1;j<=m;j++){
                    if(j==a[i]) continue;
                    dp[i][a[i]][kk]=min(dp[i][a[i]][kk],dp[i-1][j][kk-1]);
                }
            }else{
                if(i==1){
                    for(int j=1;j<=m;j++)
                        dp[i][j][1]=cost[1][j];
                    continue;
                }
                for(int j=1;j<=m;j++){
                    dp[i][j][kk]=dp[i-1][j][kk]+cost[i][j];
                    for(int l=1;l<=m;l++){
                        if(j==l) continue;
                        dp[i][j][kk]=min(dp[i][j][kk],dp[i-1][l][kk-1]+cost[i][j]);
                    }
                }        
            }
        }
    }
    ll ans=0x3f3f3f3f3f3f3f3f;
    for(int i=1;i<=m;i++)
        ans=min(ans,dp[n][i][k]);
    if(ans==0x3f3f3f3f3f3f3f3f) cout<<"-1"<<endl;
    else cout<<ans<<endl;
    return 0;
}
View Code

 http://codeforces.com/problemset/problem/279/C

dp[i][j]表示当前升上去或者降下来的最左点

#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const double eps = 1e-6;
const int N = 1e5+7;
typedef long long ll;
const ll mod = 1e9+7;
using namespace std;
int a[N];
int dp[N][2];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    int n,m; cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    dp[1][0]=1; dp[1][1]=1;
    for(int i=2;i<=n;i++){
        if(a[i]<a[i-1]){
            dp[i][0]=i;
            dp[i][1]=dp[i-1][1];
        }else if(a[i]>a[i-1]){
            dp[i][0]=dp[i-1][0];
            dp[i][1]=i;
        }else{
            dp[i][0]=dp[i-1][0];
            dp[i][1]=dp[i-1][1];
        }
    }
    for(int i=1;i<=m;i++){
        int l,r; cin>>l>>r;
        if(l<min(dp[dp[r][1]][0],dp[r][0])){
            cout<<"No
";
        }else{
            cout<<"Yes
";
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/wmj6/p/11503193.html