dp[i][j][1]代表前i个能量选取j个能量时,最少天数
dp[i][j][0]代表前i个能量选取j个能量,最少天数对应的最后一天的时长。
由于本题天数是随着时间而推移的,不能把现在的某个能量填补进前几天的“空缺”,故只能通过填补上一天的空闲或者另开一天来实现状态转移。
首先不选时,考虑继承
dp[i][j][1]=dp[i-1][j][1];
dp[i][j][0]=dp[i-1][j][0];
选的时候需要另开一天,当然就是dp[i-1][j-1][0]+a[i]>199的情况,由于我们答案要求的是最少天数,所以一旦能够修改最少天数,其配套的最后一天时长也应被修改,否则如果与当前最少天数相同时,将最后一天时长修改成最小值为佳。
dp[i-1][j-1][1]+1<dp[i][j][1]时,自然两维都要被修改成a[i].
dp[i-1][j-1][1]+1==dp[i][j][1]时,因为原来
dp[i][j][1]=dp[i-1][j][1];
dp[i][j][0]=dp[i-1][j][0];
也就是说, 前i-1个选j-1个天数比前i-1个选j个天数少一,因为其个数也少1,也就是说,前i-1选j-1时只需要n-1天,选j个时又必须多了一天,所以选的第j个一定单独在最后一天,我们考虑用a[i]来替换,取最小值。因为只有一个,也同时保证了我们数量的正确性。
即
if(dp[i-1][j-1][0]+a[i]>119)
{
if(dp[i-1][j-1][1]+1<dp[i][j][1])
{
dp[i][j][1]=dp[i-1][j-1][1]+1;
dp[i][j][0]=a[i];
}
else if(dp[i-1][j-1][1]+1==dp[i][j][1])
{
dp[i][j][0]=min(d[i][j][0],a[i]);
}
}
然后就是能装下的情况了,装下并不改变原来的天数,所以如果
dp[i-1][j-1][1]<dp[i][j][1] 直接修改二维即可
如果 dp[i-1][j-1][1]==dp[i][j][1] 也就是前i-1选j-1耗用天数和前i-1天选取j个天数相同,也就是说a[i]放在前i-1选j-1最后一天与前i-1一天选j个天数的最后一天情况取最优即可。
本题其实每一个状态和前一个状态紧密相连,仅仅更新了一次,转移时找准初始状态即可。与其说是本次循环与上次循环的比较,倒不如说是上次循环内部的比较
#include <iostream>
#include <string.h>
#include <algorithm>
#include <cstdio>
#include <stdlib.h>
#include <string>
#include <memory>
#include <queue>
# include<math.h>
# include<iomanip>
# include<map>
# define mod 10007
# include<math.h>
# include<stack>
using namespace std;
typedef long long int ll;
typedef double dl;
int dp[3010][3030][2];
int a[3010];
int main()
{
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
memset(dp,9999999,sizeof(dp));
// [1]是天数,[0]是最后一天时间
dp[0][0][0]=0;
dp[0][0][1]=0;
for(int i=1;i<=n;i++)
{
dp[i-1][0][0]=0;
dp[i-1][0][1]=0;
for(int j=1;j<=i;j++)
{
dp[i][j][1]=dp[i-1][j][1];
dp[i][j][0]=dp[i-1][j][0];
if(dp[i-1][j-1][0]+a[i]>119)
{
if(dp[i-1][j-1][1]+1<dp[i][j][1])
{
dp[i][j][1]=dp[i-1][j-1][1]+1;
dp[i][j][0]=a[i];
}
else if(dp[i-1][j-1][1]+1==dp[i][j][1])
{
dp[i][j][0]=min(d[i][j][0],a[i]);
}
}
else if(dp[i-1][j-1][0]+a[i]<=119)
{
if(dp[i-1][j-1][1]<dp[i][j][1])
{
dp[i][j][1]=dp[i-1][j-1][1];
dp[i][j][0]=dp[i-1][j-1][0]+a[i];
}
else if(dp[i-1][j-1][1]==dp[i][j][1])
{
dp[i][j][0]=min(dp[i][j][0],dp[i-1][j-1][0]+a[i]);
}
}
}
}
cout<<dp[n][k][1]+1;
return 0;
}