zoukankan      html  css  js  c++  java
  • AcWing 316. 减操作 线性dp

    //f[i,cnt] 表示前i个数字和为cnt 
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=110,M=200020;
    int hh=10000;//hh是我们的下标偏移量 
    int n,t,f[N][M],a[N],ans[N];
    void solve()
    {
        f[1][a[1]+hh]=1;//a[1]必然是正数
        f[2][a[1]-a[2]+hh]=-1;//a[2]必然是
        for(int i=3;i<=n;i++)
            for(int j=-10000+hh;j<=10000+hh;j++)
                //前i-1个数字可以组成的和,判断是否可以进行状态转移 
                if(f[i-1][j])
                {
                    f[i][a[i]+j]=1;//表示第i个数字前为+号,就说明在这一位进行了减操作 
                    f[i][j-a[i]]=-1;//表示第i个数字前为-号,就说明在i-1位进行了减操作 
                }
    
        int s=hh+t;
        for(int i=n;i>=2;i--)//回溯,确定+-号 
        {
            //判断第i个数字前的符号  
            ans[i]=f[i][s];
            //如果为1,那么就是+的 
            if(ans[i]==1)
                s-=a[i];
            else if(ans[i]==-1)
                s+=a[i];
        }
        //如果这一位为1,那么就说明在前一位进行cut操作
        //那么前一位前一位的前一位再进行时,就会变成+号 
        int cnt=0;
        for(int i=2;i<=n;i++)
            if(ans[i]==1)
            {
                cout<<i-cnt-1<<endl;
                cnt++;
            }
        //如果是-1,那么就说明在1这一位进行了操作 
        for(int i=2;i<=n;i++)
            if(ans[i]==-1)
                cout<<1<<endl;
    }
    int main()
    {
        cin>>n>>t;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        solve();
        return 0;
    } 
    
    
  • 相关阅读:
    DOM getElementById
    百度之星2014
    游艇租借
    2014年acm亚洲区域赛·鞍山站
    UVALive 4255 Guess
    UVA 10054 The Necklace
    UVA 10047 The Monocycle
    UVA 11624 Fire!
    第九届黑龙江省赛
    剑指offer系列31-----二叉树的下一个节点
  • 原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12604546.html
Copyright © 2011-2022 走看看