Algorithm 找到最低票价

Algorithm 找到最低票价,algorithm,optimization,dynamic-programming,Algorithm,Optimization,Dynamic Programming,找到在一个月的已知日期(1…30)旅行所需的最低购票成本。有三种类型的车票可供选择:1日车票有效期为1天,价格为2套;7日车票有效期为7天,价格为7套;30日车票有效期为30天,价格为25套 例如:我想在一个月的[1,4,6,7,28,30]天旅行,即1日、4日、6日。。。每月的第二天。如何购买门票,使成本降到最低 我试着用动态规划来解决这个问题,但解决方案并不能给我所有情况下的正确答案。以下是我的Java解决方案: public class TicketsCost { public s

找到在一个月的已知日期(1…30)旅行所需的最低购票成本。有三种类型的车票可供选择:1日车票有效期为1天,价格为2套;7日车票有效期为7天,价格为7套;30日车票有效期为30天,价格为25套

例如:我想在一个月的[1,4,6,7,28,30]天旅行,即1日、4日、6日。。。每月的第二天。如何购买门票,使成本降到最低

我试着用动态规划来解决这个问题,但解决方案并不能给我所有情况下的正确答案。以下是我的Java解决方案:

public class TicketsCost {
    public static void main(String args[]){
        int[] arr  =  {1,5,6,9,28,30};
        System.out.println(findMinCost(arr));
    }
    public static int findMinCost(int[] arr) {
        int[][] dp = new int[arr.length][3];
        int[] tDays = {1,7,30};
        int[] tCost = {2,7,25};

        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < 3; j++) {
                if (j==0){
                    dp[i][j]= (i+1)*tCost[j];
                }
                else{
                    int c = arr[i]-tDays[j];
                    int tempCost = tCost[j];
                    int k;
                    if (c>=arr[0] && i>0){
                        for (k = i-1; k >= 0; k--) {
                            if (arr[k]<=c){
                                c = arr[k];
                            }
                        }
                        tempCost += dp[c][j];
                        int tempCostX =  dp[i-1][j] + tCost[0];
                        tempCost = Math.min(tempCost,tempCostX);

                    }
                    dp[i][j] = Math.min(tempCost,dp[i][j-1]);
                }
            }
        }
        return dp[arr.length-1][2];
    }
}
public class TicketsCost{
公共静态void main(字符串参数[]){
int[]arr={1,5,6,9,28,30};
系统输出println(findMinCost(arr));
}
公共静态int findMinCost(int[]arr){
int[]dp=新int[arr.length][3];
int[]tDays={1,7,30};
int[]tCost={2,7,25};
对于(int i=0;i=arr[0]&&i>0){
对于(k=i-1;k>=0;k--){
如果(arr[k]让MC(d)表示从第1天到第d天的所有行程的最低费用。那么期望的答案是MC(30)

要计算MC(d),请遵守以下规定:

  • 如果在d天没有行程,那么MC(d)=MC(d−1).
    • 作为特例,对于所有d,MC(d)=0≤0
  • 否则,最低成本包括以下各项之一:
    • d天的1天通行证。在这种情况下,MC(d)=MC(d−1) +2
    • 在d天当天或之后结束的7天通行证。在这种情况下,MC(d)=min(MC(d−7) ,MC(d)−6) ,…,MC(d)−1))+7.
      • 由于MC是不减损的(增加一天不会降低最低成本),这可以简化为MC(d)=MC(d)−7) +7.(指出这一点的帽尖)
    • 涵盖整个期间的30天通行证。在这种情况下,MC(d)=25
正如您所意识到的,动态编程(自底向上递归)非常适合这种情况

为了便于编码,我建议我们首先将天数列表转换为“这是旅行日吗?”的查找表:

然后,我们可以创建一个数组来跟踪最低成本,并从索引0开始填充它:

int[] minCostUpThroughDay = new int[31];
minCostUpThroughDay[0] = 0; // technically redundant
for (int d = 1; d <= 30; ++d) {
    if (! isDayWithTrip[d]) {
        minCostUpThroughDay[d] = minCostUpThroughDay[d-1];
        continue;
    }

    int minCost;
    // Possibility #1: one-day pass on day d:
    minCost = minCostUpThroughDay[d-1] + 2;
    // Possibility #2: seven-day pass ending on or after day d:
    minCost =
        Math.min(minCost, minCostUpThroughDay[Math.max(0, d-7)] + 7);
    // Possibility #3: 30-day pass for the whole period:
    minCost = Math.min(minCost, 25);

    minCostUpThroughDay[d] = minCost;
}
int[]minCostUpThroughDay=newint[31];
minCostUpThroughDay[0]=0;//技术上冗余

对于(int d=1;d,使用与自底向上动态规划相同的方法进行求解。以下是完整的解决方案:

public class PublicTicketCost {
    public static void main(String args[]){
        int[] arr  =  {1,7,8,9,10,15,16,17,18,21,25};
        int[] tDays = {1,7,30};
        int[] tCost = {2,7,25};
        System.out.println(minCost(arr, tDays, tCost));
    }
    public static int minCost(int[] arr, int[] tDays, int[] tCost) {
        int[][] dp = new int[arr.length][tDays.length];

        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < tDays.length; j++) {

                int prevDayIndex = findPrevDayIndex(arr,i,tDays,j);
                int prevCost = prevDayIndex>=0 ? dp[prevDayIndex][tDays.length-1] : 0;
                int currCost = prevCost + tCost[j];
                if(j-1>=0){
                    currCost = Math.min(currCost, dp[i][j-1]);
                }
                dp[i][j] = currCost;
            }
        }
        //print(dp);
        return dp[arr.length-1][tDays.length-1];
    }
    private static void print(int arr[][]){
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[0].length; j++) {
                System.out.print(arr[i][j]+" ");
            }
            System.out.println();
        }
    }
    private static int findPrevDayIndex(int[] arr, int i, int[] days, int j){
        int validAfterDate = arr[i] - days[j];
        if (validAfterDate<1){
            return -1;
        }
        for (int k = i-1; k >= 0; k--) {
            if (arr[k]<=validAfterDate){
                return k;
            }
        }
        return -1;
    }
}
公共类公共票务成本{
公共静态void main(字符串参数[]){
int[]arr={1,7,8,9,10,15,16,17,18,21,25};
int[]tDays={1,7,30};
int[]tCost={2,7,25};
系统输出打印LN(最小成本(arr、tDays、tCost));
}
公共静态整数最小成本(整数[]arr,整数[]tDays,整数[]tCost){
int[][]dp=新int[arr.length][tDays.length];
对于(int i=0;i=0?dp[prevDayIndex][tDays.length-1]:0;
int currCost=prevCost+tCost[j];
如果(j-1>=0){
currCost=数学最小值(currCost,dp[i][j-1]);
}
dp[i][j]=当前成本;
}
}
//印刷(dp);
返回dp[arr.length-1][tDays.length-1];
}
专用静态无效打印(int arr[]]{
对于(int i=0;i公共类Main03v3
{
公共静态void main(字符串[]args)
{
int[]A={1,7,8,9,10,15,16,17,18,21,25};
System.out.println(“旅行天数:\r\n”+Arrays.toString(A));
int成本=解决方案(A);
System.out.println(“\r\n最小成本为”+成本);
System.out.println(“\r\n”+新字符串(新字符[40])。替换(“\0”,“-”);
}
公共静态int解决方案(int[]A)
{
如果(A==null)返回-1;
七天内=7天;
国际日成本=2,周成本=7,月成本=25;
整数比率_WeekAndDays=周成本/日成本;
int len=A.长度;
如果(len==0)返回-1;
if(周和日的长度比)
{
如果(endIdx>=startIdx+sevenDays)
endIdx=startIdx+七天;
int j=startIdx;
成本[j]=((j==0)?0:成本[j-1])+周成本;
而(++j<代码> < p>这里是包含打印输出< /p>的C++解决方案
#include <vector>
#include <iostream>
#include <cmath>
#include <algorithm>
int compute(std::vector<int> &A)
{
int sum[A.size()][A.size()+1];
for (int i = 0; i < A.size(); i++)
{
    for(int j =0; j < A.size(); j++)
    {
        sum[i][j]=2;
    }
}

for (int k = 0; k < A.size();k++)
{
    sum[k][A.size()]=0;
}

for (int i = 0; i < A.size(); i++)
{
    for(int j = 0; j < A.size(); j++)
    {
        if (i!=j)
        {
            if (sum[i][i] != 7)
            {
                int temp = abs(A[j]-A[i]);
                if (temp<7 && abs(j-i)>=3)
                {   
                    sum[i][i]=7;
                    sum[i][j]=7;
                    if (i>j)
                    {
                        for(int k = j;k < i;k++)
                            sum[i][k]=7;
                    }
                    else
                    {
                        for(int k = i;k < j;k++)
                            sum[i][k]=7;
                    } 
                }
            }
        }
    }
}

for (int i = 0; i < A.size(); ++i)
{
    for(int j = 0; j < A.size(); ++j)
    {
        if (sum[i][j]==7)
        {
            sum[i][A.size()]+=1;
        }
    }
}

for (int i = 0; i < A.size(); ++i)
{
    for (int j = 0; j < A.size()+1; ++j)
        std::cout<<sum[i][j]<<" ";
    std::cout<<std::endl;
}


int result = 0;
int row = A.size()-1;
int column = A.size()-1;
while(1)
{
    int value = sum[row][A.size()];
    if (value == 0)
        value=1;
    int temp = sum[row][column];
    result += temp;
    row = row-value;
    column = column-value;
    while (sum[row][column+1]==7 && row>=0)
    {
        row-=1;
        column-=1;
        result+=2;
    }
    if (row < 0)
        break;
}

return result;
}

int solution(std::vector<int> &A) {
if (A.size() > 24)
    return 25;
if (A.size() <= 3)
    return A.size() * 2;

return std::min(25,compute(A));
}

int main()
{
std::vector<int> AA={1,2,3,4,5,29,30};
std::vector<int> B={1,2,3,4,5};
std::vector<int> A={1,2,3,4,5,9,10,11,12,13,14,17,18,20,21};
std::vector<int> C={1,2,3,12};
std::vector<int> D={1,2,3,4,12,13,14,15,29,30};
std::vector<int> DD={1,2,3,4,5,14,17,18,19,20,23,28,29,30};
std::vector<int> CC={1,2,3,4,5,6,7,9,14,17,18,19,20,23,28,29,30};
std::cout<<solution(AA)<<std::endl;
std::cout<<solution(D)<<std::endl;
std::cout<<solution(B)<<std::endl;
std::cout<<solution(A)<<std::endl;
std::cout<<solution(C)<<std::endl;
std::cout<<solution(DD)<<std::endl;
std::cout<<solution(CC)<<std::endl;
return 0;
}
#包括
#包括
#包括
#包括
整数计算(标准::向量&A)
{
整数和[A.size()][A.size()+1];
对于(int i=0;ij)
{
对于(int k=j;kpublic class Main03v3
{
  public static void main(String[] args)
  {
    int[] A = {1,7,8,9,10,15,16,17,18,21,25};

    System.out.println("Traveling days:\r\n "+Arrays.toString(A));
    int cost = solution(A);
    System.out.println("\r\nMinimum cost is " + cost);
    System.out.println("\r\n" + new String(new char[40]).replace("\0", "-"));
  }

  public static int solution(int[] A) 
  {
    if (A == null) return -1;

    int sevenDays = 7;
    int dayCost = 2, weekCost = 7, monthCost = 25;
    int ratio_WeekAndDays = weekCost / dayCost; 

    int len = A.length;
    if (len == 0) return -1;

    if (len <= 3) return len * dayCost;

    int cost[] = new int[len];

    int i = 0;
    while (i < len)
    {
      int startIdx = i, endIdx = i + 1; 
      while (endIdx < len && A[endIdx]-A[startIdx] < sevenDays) 
        endIdx++;

      if (endIdx-startIdx > ratio_WeekAndDays)
      {
        if (endIdx >= startIdx + sevenDays) 
          endIdx = startIdx + sevenDays;  

        int j = startIdx;
        cost[j] = ((j == 0) ? 0 : cost[j-1]) + weekCost;

        while (++j < endIdx) {
          cost[j] = cost[j-1];
        }  
        i = j;
      }
      else
      {
        cost[i] = ((i == 0) ? 0 : cost[i-1]) + dayCost;
        i++;
      }  
    }
    int finalCost = Math.min(cost[len-1], monthCost);

    return finalCost;  
  }
}
#include <vector>
#include <iostream>
#include <cmath>
#include <algorithm>
int compute(std::vector<int> &A)
{
int sum[A.size()][A.size()+1];
for (int i = 0; i < A.size(); i++)
{
    for(int j =0; j < A.size(); j++)
    {
        sum[i][j]=2;
    }
}

for (int k = 0; k < A.size();k++)
{
    sum[k][A.size()]=0;
}

for (int i = 0; i < A.size(); i++)
{
    for(int j = 0; j < A.size(); j++)
    {
        if (i!=j)
        {
            if (sum[i][i] != 7)
            {
                int temp = abs(A[j]-A[i]);
                if (temp<7 && abs(j-i)>=3)
                {   
                    sum[i][i]=7;
                    sum[i][j]=7;
                    if (i>j)
                    {
                        for(int k = j;k < i;k++)
                            sum[i][k]=7;
                    }
                    else
                    {
                        for(int k = i;k < j;k++)
                            sum[i][k]=7;
                    } 
                }
            }
        }
    }
}

for (int i = 0; i < A.size(); ++i)
{
    for(int j = 0; j < A.size(); ++j)
    {
        if (sum[i][j]==7)
        {
            sum[i][A.size()]+=1;
        }
    }
}

for (int i = 0; i < A.size(); ++i)
{
    for (int j = 0; j < A.size()+1; ++j)
        std::cout<<sum[i][j]<<" ";
    std::cout<<std::endl;
}


int result = 0;
int row = A.size()-1;
int column = A.size()-1;
while(1)
{
    int value = sum[row][A.size()];
    if (value == 0)
        value=1;
    int temp = sum[row][column];
    result += temp;
    row = row-value;
    column = column-value;
    while (sum[row][column+1]==7 && row>=0)
    {
        row-=1;
        column-=1;
        result+=2;
    }
    if (row < 0)
        break;
}

return result;
}

int solution(std::vector<int> &A) {
if (A.size() > 24)
    return 25;
if (A.size() <= 3)
    return A.size() * 2;

return std::min(25,compute(A));
}

int main()
{
std::vector<int> AA={1,2,3,4,5,29,30};
std::vector<int> B={1,2,3,4,5};
std::vector<int> A={1,2,3,4,5,9,10,11,12,13,14,17,18,20,21};
std::vector<int> C={1,2,3,12};
std::vector<int> D={1,2,3,4,12,13,14,15,29,30};
std::vector<int> DD={1,2,3,4,5,14,17,18,19,20,23,28,29,30};
std::vector<int> CC={1,2,3,4,5,6,7,9,14,17,18,19,20,23,28,29,30};
std::cout<<solution(AA)<<std::endl;
std::cout<<solution(D)<<std::endl;
std::cout<<solution(B)<<std::endl;
std::cout<<solution(A)<<std::endl;
std::cout<<solution(C)<<std::endl;
std::cout<<solution(DD)<<std::endl;
std::cout<<solution(CC)<<std::endl;
return 0;
}