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); } }