[JL]最后的晚餐 动态规划(DP) codevs5318
[JL]最后的晚餐
TimeLimit:1000MS MemoryLimit:1000KB
64-bit integer IO format:%lld
Problem Description
【题库搜索“JL”查看更多建兰题库题目】
话说YZJ编的某程序超时了1000倍(- -!),所以他不得不在自己家门口亲眼见证这个电影般的场景。虽然他不想错过这个美妙的时刻,但是他的肚子一再抗议,要求先吃完这最后的晚餐。
现在YZJ准备依次吃n道菜。但是他只使用勺子和筷子吃,勺子和筷子可以交替使用,但是同一种菜只能用一种餐具,在开饭前他拿的是筷子。用勺子和筷子吃第i道菜的时间分别是a_i和b_i。吃第i道菜之前筷子和勺子交换的时间为c_i。
现在请你告诉ABC按他的计划依次吃完这n道菜,最小需要多少时间。
Input
第一行,一个正整数n(1<=n<=100)
以下n行,分别是三个正整数a_i,b_i,c_i(1<=a_i,b_i,c_i<=30000)
数据范围及提示:
所有其他输入<=30000 N<=20
Output
一个数,最短时间
SampleInput
3
20 40 20
10 4 25
90 100 5
SampleOutput
139
思路:看到这题我们会想到,这一道菜用筷子的的话,吃完这道菜要用的总的最小时间和这一道菜用勺子吃完要用的总的最小时间,那么我们就会想到要用一个状态来保存这个时间,但是我们会发现,一开始有两个状态,换勺子吃、用筷子吃,于是就要定义两个状态,一个是在第i道菜用勺子的总时间,另一个是第i道菜用筷子的总时间。那么我们就可以先将开头的状态初始化,dp[0][1]=第一道菜用筷子的时间,dp[0][0]=第一道菜换勺子的时间,然后之后的状态就是在之前是筷子还是汤匙之间转换;
这样就得到了状态转移方程;(dp[i][0]表示的是第i道菜用筷子吃的最小时间以及吃第i-1~0道菜用的最小时间,dp[i][1]同理)
#include<stdio.h> const int N=110; int Min(int a, int b){ return a<b?a:b; } int dp[N][2]; int main( ){ int n, a, b, c; scanf("%d", &n); for(int i=0; i^n; ++i){ scanf("%d%d%d", &a, &b, &c); if(!i) dp[i][0]=a+c, dp[i][1]=b; else{ dp[i][0]=Min(dp[i-1][0]+a, dp[i-1][1]+c+a); dp[i][1]=Min(dp[i-1][1]+b, dp[i-1][0]+b+c); } } printf("%d\n", Min(dp[n-1][0], dp[n-1][1])); return 0; }