leetcode[983]:Minimum Cost For Tickets

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/bless2015/article/details/88225695

本题是个求最小值问题,题目描述:如果要在一年内去旅游,现给定你旅游的日期(1-365天)的数组,一个包日车票数组价格,比如包1天2块钱,包7天7块钱,包30天15块钱这样。求一年内能把所有规定日期都旅游完的最便宜买票策略。
例:
days[1,4,6,7,8,20],表明你要在1,4,6,7,8,20去旅游。(范围为1-365)
costs[2,7,15],表明1天的车票是2块钱,7天的车票是7块钱,30天的车票是15块钱。ps只有1、7、30天三种可选。

本题我没有解决,参考了一下别人的最后弄懂了,很巧妙。下面是我自己的理解。
首先1-365是一个一维长数组,在这个数组内,有的天需要旅游,有的天不需要旅游,我们先把需要旅游的天数标记为1,以days[1,4,6,7,8,20]为例,则这个数组f大概长这样

[1,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0...0]

这里是类似计数排序的一种思想去构造的数组,参考前面博客讲计数排序。加入动态规划的思想,从数组第0为开始计算,如果
f[0]==1,说明该天去旅游了,计算其需要的车票,那么我去从costs[2,7,15]去找最小的。答案是2。则f[0]==2
f数组长下面这样:

[2,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0...0]

接着
f[1]==0,说明该天没有去旅游,则该天的花费我们也可以看做是2,是为了传递这个价格,为后面做比较用。
f长这样

[2,2,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0...0]

继续第三次循环,
f[2]==0

[2,2,2,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0...0]

f[3]==1,则计算f[3-1]+costs[0]和f[3-7]+costs[1]和f[3-30]+costs[2]的最小值,3-7和3-30都是负数,我们取到0即可。f[0]=0。发现f[3-1]+costs[0]最小,为2+2=4
f数组长这样了

[2,2,2,4,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0...0]

f[4]==1,则f数组长这样

[2,2,2,4,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0...0]

f[5]同理

[2,2,2,4,4,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0...0]

f[6]

[2,2,2,4,4,6,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0...0]

f[7]时,f[7]==1,需要比较f[7-1]+costs[0]=8和f[7-7]+costs[1]=7和f[7-7]+costs[2]=15的值,最小的为f[7-7]+costs[1]=7
则f这次长这样

[2,2,2,4,4,6,7,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0...0]

依次类推。
代码:

    public static int mincostTickets(int[] days, int[] costs) {
		int length = days.length;
    	int f[] = new int[366];
    	
    	for (int i = 0; i < days.length; i++) {
			f[days[i]]=1;
		}
    	
    	for (int i = 1; i < 365; i++) {
			if(f[i]==0){
				f[i] = f[i-1];
			}else{
				f[i] = Math.min(f[i-1]+costs[0], Math.min(f[Math.max(i-7, 0)]+costs[1],f[Math.max(i-30, 0)]+costs[2]));
			}
		}
        return f[days[length-1]];
    }

猜你喜欢

转载自blog.csdn.net/bless2015/article/details/88225695