URAL1029 Ministry

就是从第一层到最后一层,怎么走费用最小,输出经过的房间号(不用楼层)


明显的DP嘛,,,,,,

一层一层来,,,每一个点的最小费用都是左或右或下的最小费用加上本身的


先来个错误的:

#include<stdio.h>
#include<string.h>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
long long int a[101][501];
long long int dp[2][101][501]={0};
long long int pre[2][101][501]={0};
int main()
{
    long long int m,n;
    while(scanf("%lld%lld",&m,&n)!=EOF)
    {long long int i,j;
    for(i=0;i<m;i++)
    {
        for(j=0;j<n;j++) scanf("%lld",&a[i][j]);
    }
    for(i=0;i<n;i++)
    {
        dp[0][m-1][i]=a[m-1][i];
        pre[0][m-1][i]=0;
    }
    for(i=m-2;i>=0;i--)
    {
        for(j=0;j<n;j++)
        {
            dp[0][i][j]=a[i][j]+dp[0][i+1][j];
            pre[0][i][j]=(i+1)*1000+j;
        }
        for(j=0;j<n;j++)
        {
            if(j+1<n)
            {
                if(dp[0][i][j]>(dp[0][i][j+1]+a[i][j]))
                {
                    dp[0][i][j]=dp[0][i][j+1]+a[i][j];
                    pre[0][i][j]=(i)*1000+j+1;
                }
            }
            if(j-1>=0)
            {
                if(dp[0][i][j]>(dp[0][i][j-1]+a[i][j]))
                {
                    dp[0][i][j]=dp[0][i][j-1]+a[i][j];
                    pre[0][i][j]=i*1000+j-1;
                }
            }
        }
     }
        long long int minn=99999999;
        long long int qwe;
        for(i=0;i<n;i++)
        {
            if(minn>dp[0][0][i])
            {
                minn=dp[0][0][i];
                qwe=i;
            }
        }

        /*反方向!!!!!!!!*/
        for(i=0;i<n;i++)
    {
        dp[1][m-1][i]=a[m-1][i];
        pre[1][m-1][i]=0;
    }
    for(i=m-2;i>=0;i--)
    {
        for(j=0;j<n;j++)
        {
            dp[1][i][j]=a[i][j]+dp[1][i+1][j];
            pre[1][i][j]=(i+1)*1000+j;
        }
        for(j=n-1;j>=0;j--)
        {
            if(j+1<n)
            {
                if(dp[1][i][j]>(dp[1][i][j+1]+a[i][j]))
                {
                    dp[1][i][j]=dp[1][i][j+1]+a[i][j];
                    pre[1][i][j]=(i)*1000+j+1;
                }
            }
            if(j-1>=0)
            {
                if(dp[1][i][j]>(dp[1][i][j-1]+a[i][j]))
                {
                    dp[1][i][j]=dp[1][i][j-1]+a[i][j];
                    pre[1][i][j]=i*1000+j-1;
                }
            }
        }
     }
        long long int minn2=99999999;
        long long int qwe1;
        for(i=0;i<n;i++)
        {
            if(minn2>dp[1][0][i])
            {
                minn2=dp[1][0][i];
                qwe1=i;
            }
        }


        if(minn>minn2)
        {
            qwe=qwe1;
            long long int t=0;
            while(t!=m-1)
            {
                //printf("pre[t][qwe]=%d  \n",pre[t][qwe]);
                printf("%lld ",qwe+1);
                long long int t1=t;
                t=pre[1][t][qwe]/1000;
                qwe=pre[1][t1][qwe]%1000;
            }
            printf("%lld",qwe+1);
            printf("\n");
        }
        else
        {
            long long int t=0;
            while(t!=m-1)
            {
                //printf("pre[t][qwe]=%d  \n",pre[t][qwe]);
                printf("%lld ",qwe+1);
                long long int t1=t;
                t=pre[0][t][qwe]/1000;
                qwe=pre[0][t1][qwe]%1000;
            }
            printf("%lld",qwe+1);
            printf("\n");
        }

    }
    return 0;
}

能过各种样例除了

1 1

100000000

还有test3 RE了什么鬼?????



无无语


#include<stdio.h>
#include<string.h>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;

long long dyn[110][510] , a[110][510] , big, sum[110][510] ,
p[110][510][2] , o , m, n;
int main(){
   cin>>m>>n;
   for(int i=0;i<m;i++)
       for(int j=0;j<n;j++)
          cin>>a[i][j];
   for(int i=0;i<m;i++)
   {
       sum[i][0]=a[i][0];
       dyn[i][0]=1000000000;
       for(int j=1;j<n;j++)
       {
           sum[i][j]=sum[i][j-1]+a[i][j];
           dyn[i][j]=1000000000;
       }
   }

if((m==1)&&(n==1))
{
cout<<1<<endl;
return 0;
}
   dyn[m-1][0]=a[m-1][0];
   for(int i=1;i<n;i++)
   {
       dyn[m-1][i]=a[m-1][i];
   }
   for(int i=m-2;i>=0;i--)
   {
       for(int j=n-1;j>=0;j--)
       {
           for(int k=0;k<n;k++)
           {
               if(j>k)
               {
                   if(dyn[i+1][k]+sum[i][j]-sum[i][k-1]<dyn[i][j])
                   {
                       dyn[i][j]=dyn[i+1][k]+sum[i][j]-sum[i][k-1];
                       p[i][j][0]=j;
                       p[i][j][1]=k;
                   }
               }
               else
               {
                   if(dyn[i+1][k]+sum[i][k]-sum[i][j-1]<dyn[i][j])
                   {
                       dyn[i][j]=dyn[i+1][k]+sum[i][k]-sum[i][j-1];
                       p[i][j][0]=j;
                       p[i][j][1]=k;
                   }
               }
           }
       }
   }
   big=dyn[0][0];
   o=0;
   for(int i=1;i<n;i++)
   {
       if(dyn[0][i]<big)
       {
           big=dyn[0][i];
           o=i;
       }
   }
   cout<<o+1;
   if(m==1)
   {
       cout<<endl;
       return 0;
   }
   for(int i=1;i<m-1;i++)
   {
   if(p[i][o][0]<=p[i][o][1])
   {
       for(int j=p[i][o][0];j<=p[i][o][1];j++)
           cout<<" "<<j+1;
           }
           else
           {
           for(int j=p[i][o][0];j>=p[i][o][1];j--)
               cout<<" "<<j+1;
               }
           o=p[i][o][1];
   }
   cout<<" "<<o+1<<endl;
   cin>>big;
return 0;
}


身心俱疲、、、、、、



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值