蓝桥杯剪邮票问题

首先题目是这样的:

剪邮票


如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。

请你计算,一共有多少种不同的剪取方法。

请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。



题目要求的是求出所有满足条件的剪法,所以这里就用到组合问题,将所有的可能选出来,再一一进行判断,最终得出结果。

第一步:组合算法

void cbt(int low,int num){  //起始位与需要取出的个数   
if (num == 0) {  //出口
if (OK(c)) {   //判断c数组是否满足条件(代码见下文)
for (int i = 0; i < c.length; i++) {
System.out.print(c[i]+" ");
}
count++;
System.out.println();
}
}else{
for (int i = low; i < a.length; i++) {  //组合主体部分
c[num-1] = a[i];
cbt(i+1, num-1);
}
}
}

第二歩:判断条件

这里特殊说明一下,不是所有差值为1的2张邮票都是相连的,好比如4与5,为了防止太多的判断条件,所以将原数值进行修改

2 3 4

6 7 8 9

11 12 13 14

这样差值为1则一定在同一行,差值为5则一定在同一列。

boolean OK(int c[]){
boolean b = true;  //假定为与其他的邮票相连,若与其他4张邮票均不相连则false
int a[] = new int[5];//定义一个用来放连接数的数组(即该邮票与几张邮票相连)
int temp;//记录邮票相连的个数
for (int i = 0; i < c.length; i++) {
temp = 0;
for (int j = 0; j < c.length; j++) {
if (Math.abs(c[i]-c[j]) == 1||Math.abs(c[i]-c[j]) == 5) {//邮票相连的条件
temp++; 
}
}
if (temp == 0) {//如果temp为0  说明与其他4张邮票不相连,则排除(初步判断)
b = false;
}else {//否则就将相连个数记录
a[i] = temp;
}
}

//计算整个数组的相连数总数
int temp2 = 0;
for (int i = 0; i < a.length; i++) {
temp2+= a[i];
}
if (temp2 <= 6) {//如果相连数总数小于等于6,则一定不满足条件(再次判断)
b = false;
}
return b;
}

至于为什么第二次的判断条件是小于等于6。

其实很简单,第一次判断过后,唯独只有一种情况没有排除掉,如下图

下面是完整代码:

public class seven {

public static void main(String[] args) {

CBT c = new CBT();
c.cbt(0, 5);
System.out.println(c.count);
}
}


class CBT{
int a[] = {1,2,3,4,6,7,8,9,11,12,13,14};
int c[] = new int[5];
int count = 0;
void cbt(int low,int num){
if (num == 0) {
if (OK(c)) {
for (int i = 0; i < c.length; i++) {
System.out.print(c[i]+" ");
}
count++;
System.out.println();
}
}else{
for (int i = low; i < a.length; i++) {
c[num-1] = a[i];
cbt(i+1, num-1);
}
}
}

boolean OK(int c[]){
boolean b = true;
int a[] = new int[5];
int temp;
for (int i = 0; i < c.length; i++) {
temp = 0;
for (int j = 0; j < c.length; j++) {
if (Math.abs(c[i]-c[j]) == 1||Math.abs(c[i]-c[j]) == 5) {
temp++; 
}
}
if (temp == 0) {
b = false;
}else {
a[i] = temp;
}
}
int temp2 = 0;
for (int i = 0; i < a.length; i++) {
temp2+= a[i];
}
if (temp2 <= 6) {
b = false;
}

return b;
}
}

运行结果如下:(部分结果以及总数)


DESCRIPTION: 1.Analyze Problem A : sorted stamps array A={ai} ai: one stamp element in array n: array size, that is number of elements in array r: desired value of stamps F(n,r):expected result, minimum number of stamps for a given value r from n size array. S: selected stamps array S={si} 2.Choose Algorithm a.Greedy algorithm seems to be a good choice, try to solve it in O(n), i try divide array into subarry B={bi}, r should larger than every elemnt in B that is r>bi and suppose bk is the smallest element in B, so that r= bk%r, f(i,r)=(bk/r), F(n,r)=∑f(i,r). The main idea is to choose the last element who larger than desired value each time. However,it can not give us optimal solution in some condition, like A={8,5,4,1}, if r=10, this algoritm will give a solution F(n,r)=3, S={8,1,1},but the optimal solution should be F(n,r)=2, S={5,5}. b.Full search so the straight forwards algorithm is to search for every solution in A for desired value directly.However, it will always take O(n!) to go through every combination. c.Dynamic programming, at last, I decide to choose dynamic programming. analyze optimal structure, suppose in A={ai}, for a specific stamp ak,there will be two cases it is choosen so that f(i,r)=1+f(i,r-ak) , 1<=i<=k, r>=ak it is not valid so that f(i,r)=f(i-1,r) 3.Design Dynamic programming optimal structure: Compute-opt(r)= 1 + Compute-opt(r-ai) value: Compute-opt(r) = ∞ (r < 0) Compute-opt(r) = 0 (r = 0) Compute-opt(r) = 1+{Compute-opt(r-ai)} ( 1=<i<=n, r>ai>0 ) Complexity :O(nr) Memory cost:O(n+r) Compute in a bottom-up style to recursive every desired value and array. store value of Compute-opt in memory for future use, so that we can easily get value from those memory in future recursive call, and avoid compute again, that is if the array is not change, you can easily fetch result any desired value j (j < r, r is the value using for compute ). 2.For User totally, I design a small command line for this machine list below 1.Manual Operation 2.Self Auto Testing 3.Check Results q.Quit Manual Operation: when select this machine will turn to be manual mode, ask person to input stamps and desired value; Self Auto Testing:when select this machine will turn to be auto mode, show the test case already design in code after that machine will quit automatically. Check Results: only be visiable in Manual Operation, people can check desired value for the array input before, the desired value should be no more than first time input. Quit, clean all the memory and quit system.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值