阿里巴巴3.20笔试,打扑克,bfs+剪枝
//没参加3.20号的笔试,后续自己写出来的,能否AC不作保证
//找到所有的顺子
private List<int[]> selectFive(int[] cardCount){
List<int[]> result=new LinkedList<>();
for(int i=0;i<=cardCount.length-5;++i){
if(cardCount[i]>0){
int cnt=1;
for(int j=i+1;j<cardCount.length;++j){
if(cnt==5) break;
if(cardCount[j]>0) ++cnt;
else break;
}
if(cnt==5){
int[] tmp=Arrays.copyOf(cardCount,cardCount.length);
for(int k=i;k<i+5;++k){
--tmp[k];
}
result.add(tmp);
}
}
}
return result;
}
//找出所有的三连对
private List<int[]> selectSix(int[] cardCount){
List<int[]> result=new LinkedList<>();
for(int i=0;i<=cardCount.length-3;++i){
if(cardCount[i]>=2){
int cnt=1;
for(int j=i+1;j<cardCount.length;++j){
if(cnt==3) break;
if(cardCount[j]>=2) ++cnt;
else break;
}
if(cnt==3){
int[] tmp=Arrays.copyOf(cardCount,cardCount.length);
for(int k=i;k<i+3;++k){
tmp[k]-=2;
}
result.add(tmp);
}
}
}
return result;
}
//10种扑克牌A~9,每种最多四张,出牌方式可以是单张,一个对子,连续的三个对子已经连续五张的顺子,求解打完扑克牌的最少步骤数
//tip: bfs,时间复杂度略高
public int playingCard(int[] cardCount){
Queue<int[]> queue=new LinkedList<>();
Queue<Integer> cntQ=new LinkedList<>();//记录每种选择对应的步数
//Set<String> states=new HashSet<>();//记录状态,用于剪枝,貌似更慢了....
queue.add(cardCount);
cntQ.add(0);
int ans=Integer.MAX_VALUE;
int max=0;
for(int i=0;i<cardCount.length;++i) {//只出单张和对子,所需的操作数,最优解不会超过这个,用于剪枝
if(cardCount[i]==1){
max+=cardCount[i];
}else if(cardCount[i]%2==0) {
max+=cardCount[i]/2;
}else{
max+=cardCount[i]/2+1;
}
}
while (!queue.isEmpty()){
int[] tmp=queue.poll();
int cnt=cntQ.poll();
//states.add(Arrays.toString(tmp));
List<int[]> tmp5s=selectFive(tmp),tmp6s=selectSix(tmp);
//出连续的三个对
for(int[] tmp6:tmp6s){
if(cnt>=max) break;
//if(states.contains(Arrays.toString(tmp6))) continue;
queue.add(tmp6);
cntQ.add(cnt+1);
}
//出连续的五张
for(int[] tmp5:tmp5s){
if(cnt>=max) break;
//if(states.contains(Arrays.toString(tmp5))) continue;
queue.add(tmp5);
cntQ.add(cnt+1);
}
if(tmp5s.isEmpty()&&tmp6s.isEmpty()){//没有顺子和连续的三个对子,这时可以算出一种方案了
for(int i=0;i<tmp.length;++i) {
if(tmp[i]==1){//单张
cnt+=tmp[i];
}else if(tmp[i]%2==0) {//能取对子
cnt+=tmp[i]/2;
}else{
cnt+=tmp[i]/2+1;
}
}
ans=Math.min(ans,cnt);
}
}
return ans;
}
@Test
public void testPlayingCard() {
System.out.println(playingCard(new int[]{4,4,4,4,4,4,4,4,4,4}));
} #阿里笔试2020##笔试题目##阿里巴巴#