HDU 1494跑跑卡丁车

水DP  状态方程分段考虑

可以做成dp[L*N][15]或者dp[L][15]

首先是节省空间的做法(其实时间也少,因为初始化省了很多时间)

#include<iostream>
#include<stdio.h>
#include<algorithm>
#define INF 1<<30
using namespace std;
int main()
{
	 int n,d,a[10005],b[10005],dp[105][15];
	while(~scanf("%d%d",&d,&n))
	{
		for(int i=0;i<d;++i)
		{scanf("%d",&a[i]);}
		for(int i=0;i<d;i++)
		{scanf("%d",&b[i]);}
	   	for(int i=0;i<=d;i++)
		   for(int j=0;j<15;j++)
		    {
	    	    dp[i][j]=INF;
            } 
        	
     	 dp[0][0]=0;
 	   for(int k=0;k<n;k++)
 	    {
          for(int i=1;i<=d;i++)
           {
            for(int j=0;j<15;j++)
		      {
	               int before = i-1;
					    if(j==0){dp[i][0]=dp[before][5]+b[i-1];}
                         if(j>0&&j<=9){dp[i][j]=min(dp[before][j+5]+b[i-1],dp[before][j-1]+a[i-1]);}
			            if(j>=11&&j<=14){dp[i][j]=dp[before][j-1]+a[i-1];}
                         if(j==10){dp[i][j]=min(dp[before][9]+a[i-1],dp[before][14]+a[i-1]);}
		   	        
              }
          }
          for(int j=0;j<15;j++)              //把起点和终点一定要分开 不然1段n圈的数据会跪
          {
          	dp[0][j]=dp[d][j];
		  }
 	   }
	  int min=INF;
	  for(int i=0;i<15;i++)
	  {
//	  	printf("%d  ",dp[d-1][i]);
	  	if(min>dp[d][i]){min=dp[d][i];}
	  }
        printf("%d\n",min);
	}
	return 0;
}



如果不想节约空间的话就弄成L*N段 

这样做的话代码是

  

#include<iostream>
#include<stdio.h>
#include<algorithm>
#define INF 1<<30
using namespace std;
int main()
{
     int n,d,a[10005],b[10005],dp[10005][15];
    while(~scanf("%d%d",&d,&n))
    {
        for(int i=0;i<d;++i)
        {scanf("%d",&a[i]);}
        for(int i=0;i<d;i++)
        {scanf("%d",&b[i]);}
           for(int i=0;i<=d*n;i++)
           for(int j=0;j<15;j++)
            {
                dp[i][j]=INF;
            } 
            
            dp[0][1]=a[0];
         for(int i=1;i<d*n;i++)
          {
           for(int j=0;j<15;j++)
             {
               //  int before=(i+d-1)%(d);
                        int before = i-1; 
                        if(j==0){dp[i][0]=dp[before][5]+b[i%d];}
                         if(j>0&&j<=9){dp[i][j]=min(dp[before][j+5]+b[i%d],dp[before][j-1]+a[i%d]);}
                        if(j>=11&&j<=14){dp[i][j]=dp[before][j-1]+a[i%d];}
                         if(j==10){dp[i][j]=min(dp[before][9]+a[i%d],dp[before][14]+a[i%d]);}
                       
             }
          }
        
      int min=INF;
      for(int i=0;i<15;i++)
      {
          if(min>dp[d*n-1][i]){min=dp[d*n-1][i];}
      }
       printf("%d\n",min);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值