java趣味编程100实例

java趣味编程100实例
java趣味编程100实例

1_1

问题描述:根据福利彩票的规则,6个蓝色球,范围1--32,不允许重复,1个红色球,范围

1-16,自动生存6个蓝色球,1个红色球。

import java.util.Arrays;

import java.util.Random;

import java.util.Scanner;

public class Ch11_2

{

/**

* 根据给定的最小数字和最大数字,以及随机数的个数,产生指定的不重复的数组

* @param begin 最小数字(包含该数)

* @param end 最大数字(不包含该数)

* @param size 指定产生随机数的个数

*

* 实现思路:首先定义一个方法,使它能够产生6个不重复的蓝色随机数,存放到数组中, * 再产生1个红色随机数,最后他们组合在一起就是题目所求

*/

public static int[] generateRandomNumber(int begin, int end, int size) {

// 加入逻辑判断,确保begin

if (begin >= end || (end - begin) < size)

{

return null;

}

// 种子你可以随意生成,但不能重复里面存放的是你的取值范围

//本题就是 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32] int[] seed = new int[end - begin];

for (int i = begin; i < end; i ++)

{

seed[i - begin] = i;

}

int[] ranArr = new int[size];

Random ran = new Random();

// 数量你可以自己定义。这里生成了6个蓝色球的号码

for (int i = 0; i < size; i++)

{

// 得到一个位置

int j = ran.nextInt(seed.length - i);

// 得到那个位置的数值

ranArr[i] = seed[j];

// 将最后一个未用的数字放到这里,这样就把取出的数覆盖了,达到了不重复

的目的。

seed[j] = seed[seed.length - 1 - i];

}

return ranArr;

}

public static void main(String[] args)

{

i nt[] ranArr={};

i nt red;

S canner input=new Scanner(System.in);

R andom ran = new Random();

S ystem.out.println("欢迎使用双色球自动摇号系统");

S ystem.out.print("确实摇号(y/n)?");

S tring go;

g o=input.next();

w hile(go.equalsIgnoreCase("y"))

{

ranArr= generateRandomNumber(1,33,6);

red=ran.nextInt(16);

System.out.println(Arrays.toString(ranArr)+" "+red);

System.out.print("继续摇号(y/n)?");

go=input.next();

}

System.out.println("谢谢使用!");

}

}

1_2 超长整数的相加

问题描述:编写程序,实现超过整形变量存储范围数据的相加

import java.util.Arrays;

import java.util.Scanner;

public class Ch11_4

{

/**

* 实现思路:1 将两个超长的整形转换为字符串

* 2 将两个字符串变为等长,如:30812111123 298----30812111123 00000000289

* 3 将两个字符串对应相加,结果存到到另一个字符串

* 4 最后对新的字符串做进位处理

* @param args

*/

public static void main(String[] args)

{

// Scanner input=new Scanner(System.in);

// System.out.print("请输入第一个加数:");

// String addA=input.next();

// System.out.print("请输入第二个加数:");

// String addB=input.next();

String addA="30812111123";

String addB="298";

//调用方法计算结果,输出

System.out.println(addA+"+"+addB+"="+strvalue(addA,addB)); }

/**

*将两个字符串相加,得到新的字符串

*/

public static String strvalue(String addA,String addB)

{

String strvalue="";

int lenA=addA.length();

int lenB=addB.length();

int templen=0;

//调整长度相同

if(lenA>=lenB)

{

templen=lenA-lenB;

addB=maxlen(addB,templen);//调整长度,使其跟大数长度一致

}else{

templen=lenB-lenA;

addA=maxlen(addA,templen);

}

char addcharA[]=addA.toCharArray();

char addcharB[]=addB.toCharArray();

int len=addcharA.length;

int valueC[]=new int[len];

for(int i=0;i

{

//取出字符串中的数转换为数字

int a=Integer.parseInt(String.valueOf(addcharA[i]));

int b=Integer.parseInt(String.valueOf(addcharB[i]));

valueC[i]=a+b;//每项相加存储

}

System.out.println(Arrays.toString(valueC));

int tmp=0;//代表进位

//处理进位从个位开始

for(int i=valueC.length-1;i>=0;i--)

{

if(valueC[i]>=10)

{

strvalue=String.valueOf(valueC[i]+tmp-10)+strvalue; tmp=valueC[i]/10;

}else{

strvalue=String.valueOf(valueC[i]+tmp)+strvalue;

tmp=0;

}

}

return strvalue;

}

//调整长度,使其长度一样

private static String maxlen(String str,int templen)

{

String strmax=null;

StringBuffer buff=new StringBuffer();

for(int i=0;i

{

buff.append("0");

}

strmax=buff.toString()+str;

return strmax;

}

}

1_3 尾数前移

问题描述:求一个自然数N,个位数是6,将6提到最前面得到的数是N的4倍

public class Ch11_5

{

/**

* 问题分析:1 假设这个数是n6(n是从1开始的正整数)

* 2 满足关系 6n=4*(n6)

* 3 n6=n * 10 + 6; 6n=6 * Math.pow(10,i) + n; i代表的是6处在的是十位还是百位等等 (十位 i=1....)

* @param args

*/

public static void main(String[] args)

{

int n = 0;//代表6的前面部分,“n6”

int N;//6移动前,即N=n6

int M;//6移动到数字首部后,即M=6n

int buf;

int i = 0;//代表数字的长度

while(true)//穷举

{

//移动前

N = n * 10 + 6;

buf = n;

//计算数字的长度,确定6移到首部的权重,即:6代表的是十位还是百位等等

while(buf!=0)

{

i++;

buf = buf/10;

}

//移动后

M = (int)(6 * Math.pow(10,i)) + n;

//条件满足,输出,退出循环

if(M == (4*N))

{

S ystem.out.print("要找的数为:"+N);

break;

}

n++;//穷举变量修改

i = 0;//长度值复位

}

}

}

1_4国际象棋有八行八列,64个单元格,在棋盘上摆放八个皇后,使其不能相互攻击,就是说任意两个皇后不能处在同一行,同一列或同一斜线上,问一共有多少中摆法

import java.util.Arrays;

public class Ch11_6

{

static int result=0;

static int[] WeiZhi=new int[8]; //全局数组,下标代表行,里面的元素代表列(就是我们上算法分析的解向量)

static void EightQueen(int n) // 算法

{

int i,j;

int ct; //用于判断是否冲突,1代表不冲突

if (n == 8) //若8个皇后已放置完成

{

System.out.println(Arrays.toString(WeiZhi));

result++;

return;

}

for (i = 1; i <= 8; i++) //试探

{

WeiZhi[n] = i; //在该列的第i行上放置

//断第n个皇后是否与前面皇后形成攻击

ct=1;

for (j = 0; j < n; j++)

{

if (WeiZhi[j] == WeiZhi[n]) // 形成攻击

{

ct=0;

}

else if (Math.abs(WeiZhi[j] - WeiZhi[n]) == (n - j))// 形成攻击

{

ct=0;

}

else

{

}

}

if (ct==1) //没有冲突,就开始下一列的试探

EightQueen(n + 1); //递归调用

}

}

public static void main(String[] args)

{

EightQueen(0); //求解

System.out.println("一共有"+result+"种解法");

}

}

1_5 评委计分问题

问题描述:有10个评委为参赛选手打分,分数是1到100。选手最后的得分是:去掉一个最高分,去掉一个最低分,其余8个评委取平均值。

import java.util.Scanner;

public class Ch11_7

{

public static void main(String[] args)

{

Scanner in=new Scanner(System.in);

int num,i,max,min,sum,avg;

max=0; /*先假设当前的最大值max为0*/

min=100; /*先假设当前的最小值min为100*/

sum=0; /*将求累加和变量的初值置为0*/

for(i=1;i<=10;i++)

{

System.out.print("请第"+i+"评委输入分数: ");

num=in.nextInt(); /*输入评委的评分*/

sum+=num; /*计算总分*/

if(num>max)max=num; /*通过比较筛选出其中的最高分*/

if(num

}

System.out"去掉一个最高分:%d \n去掉一个最低分:%d ",max,min);

avg=(sum-max-min)/8;

System.out.printf("\n平均得分:%d ",avg); /*输出结果*/

}

}

1_6 罗马数字

将阿拉伯数字(0到1000)转换为罗马数字,对应关系如下表

import java.util.Scanner;

public class Ch11_8

{

//建立对照表

static String

a[][]={{"","I","II","III","IV","V","VI","VII","VIII","IX"},

{"","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"},

{"","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"}};

public static void main(String args[])

{

Scanner in=new Scanner(System.in);

System.out.print("请输入一个阿拉伯数字:");

int n=in.nextInt();

int t=0;

System.out.printf("%d=",n);

int i=1000;

int fz;//分子

int fm;//分母

int row;

int col;

for(int m=0;m<3;m++)

{

fz=n%i;//只取1000以下的数

fm=i/10;

t=fz/fm;//从高位向低位依次取出各位数字

row=2-m;

col=t;

System.out.printf("%s",a[row][col]+"\t");//对照表翻译输出

i=i/10;

}

System.out.printf("\n");

}

}

1_7 找假币问题

问题描述:现在有n枚硬币,其中一枚是假币,外观无法辩出。只知道假币比真币稍轻。要求仅仅使用一个天平,如何用最少的步骤找到假币?

该问题和二分法类似,可以用分治法解决。

import java.util.Scanner;

public class Ch11_9

{

static final int MAXNUM=30;

static int FalseCoin(int coin[],int low,int high) //算法

{

int i,sum1,sum2;

int re=0;

sum1=sum2=0;

if(low+1==high)//仅剩下两个硬币

{

if(coin[low]

{

re=low+1;//下标从0开始,加1

return re;

}

else

{

re=high+1;

return re;

}

}

if((high-low+1)%2 == 0) //n是偶数

{

for(i=low;i<=low+(high-low)/2;i++)

{

sum1= sum1 + coin[i]; //前半段和

}

for(i=low+(high-low)/2+1;i<=high;i++)

{

sum2 = sum2 + coin[i]; //后半段和

}

if(sum1>sum2) //前半段重,假币在后半段

{

re=FalseCoin(coin,low+(high-low)/2+1,high);//递归,在后半段中查询

return re;

}

else if(sum1

{

re=FalseCoin(coin,low,low+(high-low)/2);//递归,在前半段中查询

return re;

}

else

{

}

}

else//n是奇数

{

for(i=low;i<=low+(high-low)/2-1;i++)

{

sum1= sum1 + coin[i]; //前半段和

}

for(i=low+(high-low)/2+1;i<=high;i++)

{

sum2 = sum2 + coin[i]; //后半段和

}

if(sum1>sum2) //前半段重,假币在后半段

{

re=FalseCoin(coin,low+(high-low)/2+1,high);//递归,在后半段中查询

return re;

}

else if(sum1

{

re=FalseCoin(coin,low,low+(high-low)/2-1);//递归,在前半段中查询

return re;

}

else//前后一样重,假币在中间

{

re=low+(high-low)/2+1;//计算中间位置

return re;

}

}

return re;

}

public static void main(String[] args)

{

int[] coin=new int[MAXNUM];

int i,n;

int weizhi;

System.out.println("分治算法求解假银币问题!");

System.out.print("请输入银币总的个数:");

Scanner input=new Scanner(System.in);

n=input.nextInt(); //银币总的个数

System.out.print("请输入银币的真假:1代表假币,2代表真币");

for(i=0;i

{

coin[i]=input.nextInt(); //输入银币的真假,1代表假币,2代表真币

}

weizhi=FalseCoin(coin,0,n-1); //调用求假币方法,求解 System.out.println("在上述"+n+"个银币中,第"+weizhi+"个银币是假的!");

}

}

1_8 窃贼问题(0-1背包问题)

问题描述:有一个窃贼带着一个背包去偷东西,房间里有5件物品,其重量和价值如下:

物品一:6 公斤 48 元

物品二:5 公斤 40 元

物品三:2 公斤 12 元

物品四:1 公斤 8 元

物品五:1 公斤 7 元

窃贼希望拿到更大价值的东西,但是他的背包容量是8公斤,那么窃贼应该装上哪些东西才能达到要求?

分析:这是一类典型的0-1背包问题下面我将提供两种解法:回溯法和动态规划法

动态规划法解决0-1背包问题

动态规划法的核心就是递归方程。如果你不能推出递归方程,那你就老老实实用回溯法吧

m(i, j)是背包容量为j,可选物品为0,1,...,i时0-1背包问题的最优值。

m(i, j) = 0 j=0

m(i, j) = 0 i=0 && j < wi

m(i, j) = vi i=0 && j >= wi

m(i, j) = m(i-1, j) j < wi

m(i, j) = max{m(i-1, j), m(i-1, j-wi) + vi} j >= wi

public class Ch11_10

{

//背包容量

private int c;

//物品重量数组

private int[] w;

//物品价值数组

private int[] v;

private int[][] m;//m(i, j)是背包容量为j,可选物品为0,1,...,i时0-1背包问题的最优值。

//记录结果

private int[] x;

//最大价值

private int maxV;

//构造方法,数据初始化

public Ch11_10(int[] w, int[] v, int c)

{

this.w = w;

this.v = v;

this.c = c;

m = new int[w.length][c+1];

x = new int[w.length];

}

/** 0-1背包问题动态规划求解

*递归式

* m(i, j) = 0 j=0

* m(i, j) = 0 i=0 && j < wi

* m(i, j) = vi i=0 && j >= wi

* m(i, j) = m(i-1, j) j < wi

* m(i, j) = max{m(i-1, j), m(i-1, j-wi) + vi} j >= wi

*/

public void knapsack()

{

//初始化

for (int i = 0; i < m.length; i++)

{

m[i][0] = 0;

}

for (int j = 0; j < m[0].length; j++)

{

if (w[0] <= j)

{

m[0][j] = v[0];

}

else

{

m[0][j] = 0;

}

}

{

for (int j = 1; j < m[i].length; j++)

{

if (j < w[i])

{

m[i][j] = m[i-1][j];

}

else

{

m[i][j] = Math.max(m[i-1][j], m[i-1][j-w[i]] + v[i]);

}

}

}

maxV = m[m.length - 1][c];

System.out.println("最大值为:"+maxV );

}

//得到最优解

public int[] getResult()

{

int tmp = c;

int i;

for (i = m.length - 1; i > 0; i--)

{

//根据二维数组最后一列,相邻两行是否相等,如果相等,没有加入,否则,加入

if (m[i][tmp] == m[i-1][tmp])

{

x[i] = 0;

}

else

{

x[i] = 1;

tmp = tmp - w[i];

}

}

x[i] = (m[0][c] != 0) ? 1 : 0; //第一行,单独处理,如果非零,即加入

return x;

}

//打印数组m

public void printM()

{

{

for (int j = 0; j < m[i].length; j++)

{

System.out.printf("%2d ",m[i][j]);

}

System.out.println();

}

}

public static void main(String[] args)

{

int[] w = {6, 5, 2, 1, 1};//物品重量

int[] v = {48, 40, 12, 8, 7};//物品价格

int c=8; //背包容量

Ch11_10 k = new Ch11_10(w, v, c);//初始化数据

k.knapsack();//调用背包方法,填充动态规划表

int[] x = k.getResult();//得到最优解

System.out.println("具体组合情况如下(1代表选中,0代表未选):");

for (int i = 0; i < x.length; i++)

{

System.out.print(x[i] + " ");

}

System.out.println("\n动态规划表如下:");

k.printM();//打印动态规划表

}

}

1_9 回溯法解决0-1背包问题

package chapter11;

import java.util.Arrays;

public class Ch11_11 {

//背包容量

private int c;

//物品重量数组

private int[] w;

//物品价值数组

private int[] v;

//记录结果

private int[] x;

//记录最优解

private int[] jie;

//记录背包所装物品的最大值

private int maxValue;

public Ch11_11(int[] w, int[] v, int c){ this.w = w;

this.v = v;

this.c = c;

x = new int[w.length];

jie=new int[w.length];

}

public void DP(int n){

if(n==w.length){

if(heFa(x)){

printJie(x);

}

}else{

for(int i=0;i<2;i++){

x[n]=i;

DP(n+1);

}

}

}

/**

* 判断当前的结果x是不是合法的

* 所装物品的重量和超过背包容量就非法

* @param x2

* @return真还是假

*/

private boolean heFa(int[] x2) {

int result=0;

for(int i=0;i

if(x[i]==1)

result+=w[i];

}

if(result>c)

return false;

else

return true;

}

/**

* 打印出符合条件的所有解

* 并且将最大值存到maxValue中,将最大值的数组存放到jie中

* @param x2

* @return

*/

private void printJie(int[] x2) {

System.out.println(Arrays.toString(x));

int sum=0;

for(int i=0;i

if(x[i]==1)

sum+=v[i];

}

maxValue=maxValue>sum?maxValue:sum;

if(maxValue<=sum)

System.arraycopy(x2, 0, jie, 0, x2.length);

}

public static void main(String[] args) {

int[] w = {6, 5, 2, 1, 1};//物品重量

int[] v = {48, 40, 12, 8, 7};//物品价格

int c=8; //背包容量

Ch11_11 ch=new Ch11_11(w,v,c);

System.out.println("全部解如下:");

ch.DP(0);

System.out.println("最优解是:"+Arrays.toString(ch.jie)+"\n最大值是:"+ch.maxValue);

}

}

相关主题
相关文档
最新文档