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