打表法
没什么高尚的
基本思路就是通过暴力解法看答案有什么规律
奇数返回-1
涉及一点贪心的策略
先尽量使用装八个的袋子,看最多装到几个,不行就退,直到余数能刚好满足6的倍数,若装八个的袋子减到剩下0,就返回-1
优化:当余数大于24(6和8的最小公倍数)时就可以停止,后续的尝试没有意义了
public int minBags(int apple){
if(apple<0||apple%2==1){
return -1;
}
int bag6=-1;
int bag8=apple/8;
int rest=apple-8*bag8;
while(bag8>=0&&rest<24){
int resUse6=minBagBase6(rest);
if(restUse6!=-1){
bag6=restUse6;
break;
}
rest=apple-8*(--bag8);
}
return bag6==-1?-1:bag6+bag8;
}
public int minBagBase6(int rest){
return rest&6==0?(rest/6):-1;
}
打表
如果一个题目输入的是一个整数n,输出的也是一个整数n
在写出暴力解法的时候遍历答案,找规律
以此优化代码
注:但不是所有题目都是能这么优化
在18之后每8个数有规律:
3 -1 3 -1 3 -1 3 -1
4 -1 4 -1 4 -1 4 -1
不用去关心为什么是这个规律
public int minBagAwesome(int apple){
if((apple&1)!=0){
return -1;
}
if(apple<18){
return apple==0?0:(apple==6||apple==8)?1:(apple==12||apple==14||apple==16)?2:-1;
}
return (apple-18)/8+3;
}
吃草问题
n份青草放在一堆,先手和后手都绝对聪明,每次吃一份,每份青草分别是40,41,42…4n-1
看谁最后吃得多,返回吃得多的
public String winner1(int n){
//0 1 2 3 4
//后 先 后 先 先
if(n<5){
return (n==0||n==2)?"后手":"先手";
}
//n>=5时
int base=1;//先手决定要吃的草 4^0
while(base<=n){
//当前一个n份草,先手吃掉的是base份,n-base是留给后手的草
//母过程 先手 在子过程里是 后手
if(winner1(n-base).equals("后手")){//子过程的后手赢就代表母过程的先手赢
return "先手";//只要有一种方式能让我先手赢就可以了
}
if(base>n/4){//防止base*4之后溢出 注意这里写成n/4
break;
}
base*=4;
}
return "后手";
}
打表
找到规律:一直重复 后先后先先
public String winner2(int n){
if(n%5==0||n%5==2){
return "后手";
}else{
return "先手";
}
}