bzoj1289: [CTSC2009]移盘子

这题的标解在年鉴上面有。。
然而完全看不懂。。
甚至觉得有一点问题。。
于是我尝试地贪心了一天QAQ
最终WA收场。。
实在贪不动了。。
CODEVS上面拿了70分,还算可以吧。。
70分的贪心CODE:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int N=1005;
int s[N];
int n;
int ans=(1<<30);
int mymin (int x,int y){return x<y?x:y;}

int a[N],b[N];//把两个杆拿出来   从上往下放吧 
int a_tot,b_tot;
int next[N];//下一个在哪里 
bool better (int x)//第x位往后是否更优 
{
    int tot=0;
    bool tf=false;
    for (int u=x+1;u<next[x];u++)
    {
        if (s[u]==1) 
        {
            tot++;
            tf=true;
        }
        else 
            if (tf)
                tot--;
    }
    return tot<1;
}
void solve (int x)//先完成哪一个 
{
    int lalal=0;//有多少个这个东西
    int Next=-1;
    int sum=0;//现在已经走了多少步了
    for (int u=n;u>=1;u--)
    {
        if(s[u]==x) 
        {
            sum++;
            next[u]=Next;
            Next=u;
        }
    }
    int u;
    next[0]=Next;
    int c[N],tot=0;//那一根棍子的东西 

    bool tf=false;//是否已经出现了不合法 
    for (u=0;next[u]!=-1;u=next[u])
    {
        if (tf==false)
        {
            if (better(u))
            {
                for (int i=u+1;i<next[u];i++)
                    if (s[i]!=1)
                    {
                        sum++;
                    }
                for (int i=u+1;i<next[u];i++)
                    if (s[i]==1)
                    {
                        sum=sum+2;
                        c[++tot]=s[i];
                    }
            }
            else tf=true;
        }
        if (tf==true)
        {
            for (int i=u+1;i<next[u];i++)
            {
                c[++tot]=s[i];
                sum++;
            }
        }
        for (int i=u+1;i<next[u];i++)
            if (s[i]==1)
                tf=true;
    }
    /*现在是到第i根*/
    u++;
    a_tot=0,b_tot=0;
    for (int i=u;i<=n;i++) a[++a_tot]=s[i];
    for (int i=tot;i>=1;i--) b[++b_tot]=c[i];
/*  printf("%d\n",sum);
    for (int i=1;i<=a_tot;i++) printf("%d ",a[i]);
    printf("\n");
    for (int i=1;i<=b_tot;i++) printf("%d ",b[i]);
    printf("\n");*/
    while (a_tot>0&&a[a_tot]==1)
        a_tot--;
    while (b_tot>0&&b[b_tot]!=1)
        b_tot--;

    int k1=0,k2=0;
    for (int i=a_tot;i>=1;i--)
    {
        if (a[i]==1)
            break;
        k1++;       
    }
    for (int i=b_tot;i>=1;i--)
    {
        if (b[i]!=1)
            break;
        k2++;
    }
    int k3=0,k4=0;
    for (int u=1;u<=a_tot;u++)
    {
        if (a[u]==1) break;
        k3++;
    }
    for (int u=1;u<=b_tot;u++)
    {
        if (b[u]!=1) break;
        k4++;
    }
    ans=min(ans,sum+k1+k2+min(k1,k2)+2*(a_tot-k1)+2*(b_tot-k2));//第一种贪心策略

    /*第二种贪心策略*/
    lalal=0;
    for (int i=1;i<=b_tot;i++)
    {
        if (b[i]==1) lalal++;
        else lalal=lalal+2;
    }
    ans=min(ans,sum+lalal+a_tot*2);
    /*第三种贪心策略*/
    lalal=0;
    for (int i=1;i<=a_tot;i++)
    {
        if (a[i]==1) lalal=lalal+2;
        else lalal++;
    }
    ans=min(ans,sum+lalal+b_tot*2);
}
int main()
{
    scanf("%d",&n);
    for (int u=1;u<=n;u++)
        scanf("%d",&s[u]);
    solve(2);
    solve(3);
    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值