2022绵阳+dp经典问题

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2022绵阳+dp经典问题相关的知识,希望对你有一定的参考价值。

J. Middle Race

构造方程:y=a*x+b*y+c*z,使得你获得的分数y尽可能地逼近整个游戏总分的均值。
这一点我是想到的!!!为什么没立刻反应到?
对于参数a值进行1~n的枚举;参数b进行二分;参数c便用n去减。

#pragma-GCC-optimize("-Ofast");
#include <bits/stdc++.h>
#define endl '\\n'
#define int long long
#define ios ios::sync_with_stdio(false)

using namespace std;
const int N =2e5+5;
const int inf=1e18;
const int mod=1e9+7;
const double eps=1e-8;
int n,a,b,c,sa,sb,sc,dis,tar;

void solve()

    cin>>n>>a>>b>>c;
    a=a*3;b=b*3;c=c*3;
    if(a>b) swap(a,b);if(a>c) swap(a,c);if(b>c) swap(b,c);
    tar=(a+b+c)*n/3;
    dis=tar-n*a;
    for(int i=0;i<n;i++)
    
        int l=0,r=n-i,mid,ans;
        while(l<=r)
        
            mid=(l+r)/2;
            int tmp=i*a+mid*b+(n-i-mid)*c;
            if(tmp>=tar)
            
                l=mid+1;
                if(tmp-tar<dis) dis=tmp-tar,sa=i,sb=mid,sc=n-i-mid;
            
            else
            
                r=mid-1;
                if(tar-tmp<dis) dis=tar-tmp,sa=i,sb=mid,sc=n-i-mid;
            
        

    
    for(int i=1;i<=n;i++)
    
        if(i<=sa)
            cout<<a/3<<endl;
        else if(i<=sa+sb)
            cout<<b/3<<endl;
        else
            cout<<c/3<<endl;
        fflush(stdout);
        int y,z;
        cin>>y>>z;
    


signed main()

    ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;




G. Let Them Eat Cake

一个签到题。如果使用vector的删除操作会比较麻烦,用两个vector不断更新来回赋值也可做到筛选的操作。

#include <bits/stdc++.h>
#define endl '\\n'
#define int long long
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))

using namespace std;
const int N =2e5+5;
const int inf=1e18;
const int mod=1e9+7;
const double eps=1e-8;
int n;

void solve()

    vector<int>a,b;
    cin>>n;
    for(int i=1;i<=n;i++)
    
        int x;cin>>x;
        b.push_back(x);
    
    int ans=0;
    while(1)
    
        if(b.size()<=1) break;
        for(int x:b) a.push_back(x);
//        for(int x:a)
//            cout<<x<<" ";
//        cout<<endl;
        b.clear();
        for(int i=0;i<a.size();i++)
        
            if(i==0&&a[i]>a[i+1])
                b.push_back(a[i]);
            else if(i==a.size()-1&&a[i]>a[i-1])
                b.push_back(a[i]);
            else if(a[i]>a[i-1]&&a[i]>a[i+1])
                b.push_back(a[i]);
        
        a.clear();
        ans++;
    
    cout<<ans<<endl;

signed main()

    ios;
//    int T;cin>>T;
//    while(T--)
        solve();
    return 0;




1.矩阵连乘,求最小计算次数

#include <bits/stdc++.h>
#define endl '\\n'
#define int long long
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))

using namespace std;
const int N =2e5+5;
const int inf=1e18;
const int mod=1e9+7;
const double eps=1e-8;
int n,row[1005],col[1005],p[1005],s[1005][1005],dp[1005][1005];
void dfs(int i,int j)

    if(i==j)
    
        cout<<"A"<<i;
        return;
    
    cout<<"(";
    dfs(i,s[i][j]);
    dfs(s[i][j]+1,j);
    cout<<")";

void solve()

    cin>>n;
    for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++) dp[i][j]=inf;
    for(int i=1;i<=n;i++)
        dp[i][i]=0;
    for(int i=1;i<=n;i++) cin>>row[i]>>col[i];
    p[0]=row[1];
    for(int i=1;i<=n;i++)
        p[i]=col[i];
    for(int len=2;len<=n;len++)
    
        for(int i=1;i<=n-len+1;i++)
        
            int j=i+len-1;
            dp[i][j]=dp[i+1][j]+p[i-1]*p[i]*p[j];
            s[i][j]=i;
            for(int k=i+1;k<j;k++)
            
                int tmp=dp[i][k]+dp[k+1][j]+p[i-1]*p[k]*p[j];
                if(tmp<dp[i][j])
                
                    dp[i][j]=tmp;
                    s[i][j]=k;
                
            
        
    
    cout<<dp[1][n]<<endl;
    dfs(1,n);

signed main()

    ios;
    solve();
    return 0;

备忘录方法实现:自顶向下

#include <bits/stdc++.h>
#define endl '\\n'
#define int long long
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))

using namespace std;
const int N =2e5+5;
const int inf=1e18;
const int mod=1e9+7;
const double eps=1e-8;
int n,row[1005],col[1005],p[1005],s[1005][1005],dp[1005][1005];
void print(int i,int j)

    if(i==j)
    
        cout<<"A"<<i;
        return;
    
    cout<<"(";
    print(i,s[i][j]);
    print(s[i][j]+1,j);
    cout<<")";

int dfs(int l,int r)

    if(dp[l][r]!=-1) return dp[l][r];
    if(l==r) return 0;
    int tmp=dfs(l,l)+dfs(l+1,r)+p[l-1]*p[l]*p[r];
    s[l][r]=l;
    for(int k=l+1;k<r;k++)
    
        int res=dfs(l,k)+dfs(k+1,r)+p[l-1]*p[k]*p[r];
        if(res<tmp)
            tmp=res,s[l][r]=k;
    
    return dp[l][r]=tmp;

void solve()

    cin>>n;
    for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++) dp[i][j]=-1;
    for(int i=1;i<=n;i++)
        dp[i][i]=0;
    for(int i=1;i<=n;i++) cin>>row[i]>>col[i];
    p[0]=row[1];
    for(int i=1;i<=n;i++)
        p[i]=col[i];
    cout<<dfs(1,n)<<endl;
    print(1,n);

signed main()

    ios;
    solve();
    return 0;

最大字段和

O(n)复杂度

#include <bits/stdc++.h>
#define endl '\\n'
#define int long long
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))

using namespace std;
const int N =2e5+5;
const int inf=1e18;
const int mod=1e9+7;
const double eps=1e-8;
int n,a[N];

void solve()

    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    int ans=0,sum=0,beg,l,r;
    for(int i=1;i<=n;i++)
    
        if(sum>0) sum+=a[i];
        else
        
            sum=a[i];
            beg=i;
        
        if(sum>ans)
        
            ans=sum;l=beg;r=i;
        
    
    cout<<l<<" "<<r<<" "<<ans<<endl;

signed main()

    ios;
    solve();
    return 0;




以上是关于2022绵阳+dp经典问题的主要内容,如果未能解决你的问题,请参考以下文章

经典算法问题——01背包

hdu2196 树形dp经典|树的直径

POJ 1015 Jury Compromise(dp坑)

2022山东省赛 B - Minimum Expression(dp)

2022山东省赛 B - Minimum Expression(dp)

2022山东省赛 B - Minimum Expression(dp)