水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;
}