POJ 2609 Ferry Loading

双塔DP+输出路径。

由于内存限制,DP只能开滚动数组来记录。

我的写法比较渣,但是POJ能AC,但是ZOJ依旧MLE,更加奇怪的是Uva上无论怎么改都是WA,其他人POJ过的交到Uva也是WA。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<algorithm>
using namespace std;

int dp[2][20000+10];
struct P
{
    int x,y;
    int f;
}pre[505][20000+10];
int sum;
int a[505],tot;

void read()
{
    while(1)
    {
        scanf("%d",&a[tot+1]);
        if(a[tot+1]==0) break;
        tot++;
    }

    for(int i=0;i<=tot;i++)
        for(int j=0;j<=2*sum;j++)
            pre[i][j].f=-1;
    
    for(int j=0;j<=2*sum;j++) dp[1][j]=dp[0][j]=0x7FFFFFFF;
}

void init()
{
    sum=sum*100;
    tot=0;
}

void work()
{
    int now=0;
    dp[0][a[1]+sum]=0;
    pre[1][a[1]+sum].f=0;
    dp[0][0-a[1]+sum]=0;
    pre[1][0-a[1]+sum].f=1;

    for(int i=2;i<=tot;i++)
    {
        now=now^1;
        for(int j=0;j<=2*sum;j++) dp[now][j]=0x7FFFFFFF;
        for(int j=0;j<=2*sum;j++)
        {
            if(dp[now^1][j]==0x7FFFFFFF) continue;


            int tmp=j-sum;

            if(tmp>=0)
            {
                if(dp[now^1][j]+tmp+a[i]<=sum&&dp[now^1][j]<dp[now][tmp+a[i]+sum])
                {
                    dp[now][tmp+a[i]+sum]=dp[now^1][j];
                    pre[i][tmp+a[i]+sum].x=i-1;
                    pre[i][tmp+a[i]+sum].y=j;
                    pre[i][tmp+a[i]+sum].f=0;
                }

                if(max(tmp,a[i])+dp[now^1][j]<=sum&&dp[now^1][j]+min(tmp,a[i])<dp[now][tmp-a[i]+sum])
                {
                    dp[now][tmp-a[i]+sum]=dp[now^1][j]+min(tmp,a[i]);
                    pre[i][tmp-a[i]+sum].x=i-1;
                    pre[i][tmp-a[i]+sum].y=j;
                    pre[i][tmp-a[i]+sum].f=1;
                }
            }

            else
            {
                tmp=-tmp;
                if(dp[now^1][j]+tmp+a[i]<=sum&&dp[now^1][j]<dp[now][0-(tmp+a[i])+sum])
                {
                    dp[now][0-(tmp+a[i])+sum]=dp[now^1][j];
                    pre[i][0-(tmp+a[i])+sum].x=i-1;
                    pre[i][0-(tmp+a[i])+sum].y=j;
                    pre[i][0-(tmp+a[i])+sum].f=1;
                }

                if(max(tmp,a[i])+dp[now^1][j]<=sum&&dp[now^1][j]+min(tmp,a[i])<dp[now][a[i]-tmp+sum])
                {
                    dp[now][a[i]-tmp+sum]=dp[now^1][j]+min(tmp,a[i]);
                    pre[i][a[i]-tmp+sum].x=i-1;
                    pre[i][a[i]-tmp+sum].y=j;
                    pre[i][a[i]-tmp+sum].f=0;
                }

            }
        }
    }
}

void output()
{
    bool flag=0;
    int now_i,now_j;
    for(int i=tot;i>=1;i--)
    {
        for(int j=2*sum;j>=0;j--)
        {
            if(pre[i][j].f!=-1)
            {
                now_i=i;
                now_j=j;
                flag=1;
                break;
            }
        }
        if(flag) break;
    }

    if(flag==0) {printf("0\n");return;}
    printf("%d\n",now_i);
 
    stack<int>S;

    while(1)
    {
        if(pre[now_i][now_j].f==-1) break;
        S.push(pre[now_i][now_j].f);

        int newx,newy;
        newx=pre[now_i][now_j].x;
        newy=pre[now_i][now_j].y;
        now_i=newx;
        now_j=newy;
    }

    int k=1;
    int left=0;
    int right=0;

    while(!S.empty())
    {
        if(S.top()==0) 
        {
            printf("port\n");
            left=left+a[k];k++;
        }
        else 
        {
            printf("starboard\n");
            right=right+a[k];k++;
        }
        S.pop();
    }
}

int main()
{
    scanf("%d",&sum);
    init();
    read();
    work();
    output();
    return 0;
}

 

你可能感兴趣的:(POJ 2609 Ferry Loading)