leetcode 983.最低票价

思考一会发现,假设dp[i]意为前i+1天旅行所需的最低费用,也就是从前往后进行dp,发现不好找到状态转移方程。

观察思考发现,由于每一张通行证都是购买后生效,所以每一张通行证都具有“后对前后无效性”

eg:第10天买与不买、买啥通行证,不会影响前9天买啥通行证,但是前9天买的通行证会影响第10天买不买、买啥通行证

因此,我们采用从后往前的dp

dp[i]:后365-i+1天的最小花费

dp[i]=\left\{\begin{matrix} dp[i]=dp[i+1],,//NotTravel\\ dp[i]=min(c[0]+dp[i+1],c[1]+dp[i+7],c[2]+dp[i+30]),,//Travel \end{matrix}\right.

优化一下:上述dp[i]意思中,包含了365天,但是题目给出的数据很多并不是第365天还要旅游(也就是d[n-1]并不都是365),因此我们可以让dp[i]意为:后d[n-1]-i+1天的最小花费,因此节省了空间。

再优化一下:在判断某一天是不是要旅行时,由于题目给出 d中数字大小严格递增 的条件,因此判断第i天是否旅行时,如果遍历到d中某个元素已经>i了,说明第i天不旅行,因此就可以跳出遍历

再再优化一下:还是在判断某一天是不是要旅行时,如果第d[j]天已经被访问到了(i等于过d[j]了),那么下一次访问到的旅游的天就是d[j-1],因此之后只需判断 i 是否等于d[j-1]即可,每一次访问到d[j],就让j--,注意不要越界

给出最终代码,有几率可以打败全世界的人QAQ

    int min3(int a,int b,int c){
        int temp=a<b?a:b;
        return temp<c?temp:c;
    }
    int mincostTickets(vector<int>& d, vector<int>& c) {
        int n=d.size();
        vector<int> dp(d[n-1]+40);
        dp[d[n-1]]=min3(c[0],c[1],c[2]);
        int j=n-2;
        for(int i=d[n-1]-1;i>=1;i--){
            /*bool flag=false;
            for(int j=0;   j<n-1   ;j++){
                if(d[j]>i)
                    break;
                if(i==d[j]){
                    dp[i]=min3(c[0]+dp[i+1],c[1]+dp[i+7],c[2]+dp[i+30]);
                    flag=true;
                    break;
                }
            }
            if(!flag){
                dp[i]=dp[i+1];
            }*/  //这是第一次优化后的源代码
            if(j<0 || i!=d[j]){
                dp[i]=dp[i+1];
            }
            else{
                dp[i]=min3(c[0]+dp[i+1],c[1]+dp[i+7],c[2]+dp[i+30]);
                j--;
            } //这是第二次优化后的更改代码
        }
        return dp[1];
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值