UOJ#123. 【NOI2013】小Q的修煉

第一次完整做完一道題答….
這道題答似乎算是十分友好的

前面幾個點的代碼沒存,只有最後幾個點的代碼(不過後來看了一下感覺這個代碼是能跑所有點的)

case1,2

寫個暴力遍歷所有情況,case2要跑一會

case3

我們看一下這個train3.in
發現他分成了很多塊,每個塊的大小是170,在每個塊內他會對變量2~12修改,在塊的末尾,他會讓1加上這些變量,然後把除了2的變量清空(變量2在所有塊中只改了1次,其他操作也均不涉及他所以我們可以忽略2),然後跳到下個塊
因此不同塊之間是互不影響的,我們可以對每個塊內爆搜,再把這些塊拼起來輸出

case4,5,6

變量只有2個,且沒有涉及變量1的判斷,詢問,且變量2只有在一開始是加的,後面全是減的
再觀察一下數據發現,把2初始加的值視爲資金,每個塊內相當與花錢買成就(變量1),你買不起時可以選擇跳過,你買得起時也可以選擇跳過,且所有操作都只會往後面的操作跳
於是可以做個dp,f[i][j]表示dp到第i個操作,還未進行第i個操作,剩餘資金j的最大成就,輸出方案就記錄一個p[i][j] 表示f[i][j] 這個狀態是從哪裏轉移過來的

case7,8,9,10

變量2仍然只在開頭加了一次
發現數據仍然分成了若干塊,每個塊內變量2只會減1次,然後對3~12做一些修改,在塊的末尾把這些變量加到成就上然後清零
每個塊只會往後面的塊跳,但不一定是連着的下一個塊
和上面類似的,在每個塊內爆搜,可以處理出這個塊內相當於你可以選擇花費一些資金買一些成就,不管是否買不買得起你都可以選擇跳到後面的某個塊內
把上面的塊內爆搜和dp結合起來
f[i][j] 表示dp到第i個塊,還未進行第i個塊的操作,剩餘資金j,的最大成就,方案同樣記錄一個p[i][j] ,把最優解經過的若干個塊拼起來後再把塊內的路徑展開接在一起

具體有些細節不好描述(你們寫完跑不出來或者跑出錯的調一下就知道了2333)

code:

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define pb push_back
#define inf 1e9
using namespace std;

inline int read()
{
    int x,f=1; char c;
    while(!((c=getchar())>='0'&&c<='9')) if(c=='-') f=-1;
    x=c-'0';
    while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
    return x*f;
}
inline void up(int &a,const int &b){if(a<b)a=b;}
const int maxn = 36000;
const int maxc = 1005;

int n,m;
struct data{int t,x;};
struct node
{
    int type,sig;
    data x,y;
    int to[2];
}op[maxn];

char str[110];
void Input()
{
    for(int i=1;i<=n;i++)
    {
        scanf("%s",str);
        if(str[0]=='v')
        {
            op[i].type=1;
            op[i].x=(data){1,read()};
            scanf("%s",str); op[i].sig=str[0]=='+'?1:-1;
            scanf("%s",str); op[i].y.t=str[0]=='v',op[i].y.x=read();
        }
        else if(str[0]=='s')
        {
            op[i].type=2;
            op[i].to[0]=read(),op[i].to[1]=read();
        }
        else
        {
            op[i].type=3;
            scanf("%s",str); op[i].x.t=str[0]=='v'; op[i].x.x=read();
            scanf("%s",str); op[i].y.t=str[0]=='v'; op[i].y.x=read();
            op[i].to[0]=read(),op[i].to[1]=read();
        }

        if(op[i].to[0]<1||op[i].to[0]>n) op[i].to[0]=n+1;
        if(op[i].to[1]<1||op[i].to[1]>n) op[i].to[1]=n+1;
    }
}

struct Block
{
    int l,r;
    int vy[2],vd[2],vc[2],ful;
    vector<int>ansi;
}b[maxn]; int bn;
int bel[maxn];

int ans;
int now[20];
int t[maxn],tp;
int nowb;

void dfs(const int i)
{
    if(i<b[nowb].l||i>b[nowb].r)
    {
        if(ans<now[1])
        {
            b[nowb].vy[1]=i,b[nowb].vd[1]=now[2]-op[1].y.x;
            ans=now[1];
            b[nowb].ansi.clear();
            for(int i=1;i<=tp;i++) b[nowb].ansi.pb(t[i]);
        }
        return;
    }

    if(op[i].type==1)
    {
        int tmp=op[i].y.t?now[op[i].y.x]:op[i].y.x;
        now[op[i].x.x]+=tmp*op[i].sig;

        dfs(i+1);

        now[op[i].x.x]-=tmp*op[i].sig;
    }
    else if(op[i].type==2)
    {
        int tc=0;
        t[++tp]=tc,dfs(op[i].to[tc]),tp--;
        t[++tp]=!tc,dfs(op[i].to[!tc]),tp--;
    }
    else
    {
        int x=op[i].x.t?now[op[i].x.x]:op[i].x.x,y=op[i].y.t?now[op[i].y.x]:op[i].y.x;
        if(x<y) dfs(op[i].to[0]);
        else dfs(op[i].to[1]);
    }
}

int f[maxn][maxc],p[maxn][maxc],pc[maxn][maxc];
void dp()
{
    for(int i=1;i<=bn;i++) for(int j=0;j<maxc;j++) f[i][j]=-inf;
    f[1][op[1].y.x]=0;

    for(int i=1;i<bn;i++) for(int j=0;j<maxc;j++) if(f[i][j]!=-inf)
    {
        if(j+b[i].vd[0]>=0)
        {
            int y=b[i].vy[0],nj=j+b[i].vd[0];
            if(f[bel[y]][nj]<f[i][j]+b[i].vc[0]) f[bel[y]][nj]=f[i][j]+b[i].vc[0],p[bel[y]][nj]=i,pc[bel[y]][nj]=0;
        }
        if(j+b[i].vd[1]>=0)
        {
            int y=b[i].vy[1],nj=j+b[i].vd[1];
            if(f[bel[y]][nj]<f[i][j]+b[i].vc[1]) f[bel[y]][nj]=f[i][j]+b[i].vc[1],p[bel[y]][nj]=i,pc[bel[y]][nj]=1;
        }
    }
}


int main()
{
    freopen("train8.in","r",stdin);
    freopen("train8.out","w",stdout);

    scanf("%d%d",&n,&m);

    srand(1000007);

    Input();

    int ssum=0;
    b[bn=1].l=2;
    for(int i=2;i<=n;i++)
    {
        if(op[i].type==1&&op[i].x.x==12&&op[i].y.t&&op[i].y.x==12&&op[i].sig==-1)
        {
            b[bn].r=i; b[bn].ful=0;
            for(int j=b[bn].l;j<=b[bn].r;j++) 
            {
                bel[j]=bn;
                if(op[j].type==2&&!b[bn].ful)
                {
                    b[bn].ful=1;
                    b[bn].vy[0]=op[j].to[1],b[bn].vd[0]=0,b[bn].vc[0]=0;
                }
            }

            ans=-inf,nowb=bn; now[2]=op[1].y.x; dfs(b[bn].l);
            b[bn].vc[1]=ans;
            ssum-=b[bn].vd[1];

            b[++bn].l=i+1;
        }
    }
    bel[n+1]=bn; b[bn].r=n+1;
    for(int i=b[bn].l;i<=b[bn].r;i++) bel[i]=bn;

    dp();

    int x=bn,y=0;
    for(int i=1;i<maxc;i++) if(f[x][i]>f[x][y]) y=i;
    tp=0;
    while(x!=1)
    {
        int i=p[x][y];
        if(pc[x][y]==0)
        {
            if(y+b[i].vd[1]>=0) t[++tp]=1;
            y-=b[i].vd[0];
        }
        else
        {
            for(int j=(int)b[i].ansi.size()-1;j>=0;j--) t[++tp]=b[i].ansi[j];
            y-=b[i].vd[1];
        }
        x=i;
    }
    for(int i=tp;i>=1;i--) printf("%d\n",t[i]+1);
    //for(int i=1;i<=ansn;i++) printf("%d\n",ansi[i]+1);

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章