回溯法

 24点问题

问题描述:给定4个正整数,用算术运算符 + - * / 将这4个正整数连接起来,是最终的得数恰为24点。
   
数据输入:由文件input.txt给出输入数据,第一行有4个正整数。
   
结果输出:将计算24的算术表达式输出到文件output.txt。如果有多个满足要求的表达式,只要输出一组,每一步算式用分号隔开。如果无法得到24则输出“No Solution
   
输入文件示例:1 2 3 7
   
输出文件示例:2+1=37*3=2121+3=24

分析:对输入的4个数a,b,c,d与运算符+,-,*,/的所有组合用回溯法进行搜索。

 

算法实现Java代码:

public class Count24 { public boolean found; public float[][] r = new float[6][6]; public void search(int k,float[] d){ int i,j,m,t; float a,b; float[] e = new float[5]; if(k==1){ if((int)((d[1]-24)*10000)==0){ outanswer(); found=true; } }else{ for(i=1;i<=k-1;i++) for(j=i+1;j<=k;j++){ a=d[i]; b=d[j]; if(a<b){ float s = a; a = b; b = s; } for(m=1,t=0;m<=k;m++) if((m!=i) && (m!=j)) e[++t] = d[m]; r[5-k][1]=a; r[5-k][3]=b; r[5-k][4]=-1; for(m=1;m<=5;m++){ switch(m){ case 1:r[5-k][4]=a+b; break; case 2:r[5-k][4]=a-b; break; case 3:r[5-k][4]=a*b; break; case 4:if(b!=0) r[5-k][4]=a/b;break; case 5:if(a!=0) r[5-k][4]=b/a;break; } r[5-k][2]=m; if(r[5-k][4]!=-1){ e[t+1]=r[5-k][4]; search(k-1,e); } } } } } public void outanswer(){ for(int i=1;i<=3;i++){ switch((int)r[i][2]){ case 1: System.out.print(r[i][1]+ "+" + r[i][3]);break; case 2: System.out.print(r[i][1]+ "-" + r[i][3]);break; case 3: System.out.print(r[i][1]+ "*" + r[i][3]);break; case 4: System.out.print(r[i][1]+ "/" + r[i][3]);break; case 5: System.out.print(r[i][3]+ "/" + r[i][1]);break; } System.out.print(" = " + r[i][4] + ";"); } System.out.println(); } public static void main(String[] args) throws IOException { Count24 c = new Count24(); float[] d = new float[5]; c.found = false; for(int i=0;i<6;i++) for(int j=0;j<6;j++) c.r[i][j] = 0; System.out.println("请输入4个正整数"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); for(int i=1;i<=4;i++){ String str = br.readLine(); d[i] = Integer.parseInt(str); } c.search(4, d); if(!c.found) System.out.println("No answer!"); } }

 

 

 

0-1背包问题

问题描述:给定n种物品和一个背包。物品i的重量是wi,其价值是vi,背包的容量为C。应如何选择装入背包的物品,使得装入背包中物品的总价值最大?在选择装入背包的物品时,对每种物品i只有2种选择,即装入背包或不装入背包。不能将物品i装入背包多次,也不能只装入部分的物品i

分析:用搜索子集数的一般算法解决。

 

class Goods{ public int ID; public float d; } public class Knap { int c; //背包容量 int n; //物品数 int[] w; //物品重量数组 int[] p; //物品价值数组 int cw; //当前重量 int cp; //当前价值 int bestp; //当前最优值 int[] bestx; //当前最优解 int[] x; //当前解 public void print(){ for(int m=1;m<=n;m++){ System.out.println(bestx[m]); } } //上界函数 int Bound(int i){ //计算上界 int cleft = c-cw; //剩余容量 int b = cp; //以物品单位重量价值递减序装入物品 while(i<=n&&w[i]<=cleft){ cleft -= w[i]; b += p[i]; i++; } //装满背包 if(i<=n) b += p[i]/w[i]*cleft; return b; } //回溯 void Backtrack(int i){ if(i>n){ if(bestp<cp){ for(int j=1;j<=n;j++) bestx[j] = x[j]; bestp=cp; } return; } if(cw+w[i]<=c){ //搜索左子树 x[i]=1; cw+=w[i]; cp+=p[i]; Backtrack(i+1); cw-=w[i]; cp-=p[i]; } if(Bound(i+1)>bestp){ //搜索右子树 x[i]=0; Backtrack(i+1); } } //为Backtrack初始化 public int Knapsack(int price[],int weight[],int cap,int num){ int W=0; int P=0; int i=1; this.n = num; Goods[] Q = new Goods[num]; for(i=0;i<num;i++){ Q[i] = new Goods(); Q[i].ID = i; Q[i].d = (float) price[i]/weight[i]; P+=price[i]; W+=weight[i]; } if(W<=cap) return P; //装入所有物品 //依物品单位重量递减排序 Goods f; for(i=0;i<num;i++) for(int j=i;j<num;j++){ if(Q[i].d<Q[j].d){ f = Q[i]; Q[i] = Q[j]; Q[j] = f; } } this.p = new int[num+1]; this.w = new int[num+1]; this.x = new int[num+1]; this.bestx = new int[num+1]; this.x[0] = 0; this.bestx[0] = 0; for(i=1;i<=num;i++){ p[i] = price[Q[i-1].ID]; w[i] = weight[Q[i-1].ID]; //System.out.println(i+ " " +p[i] +" " + w[i]); } this.c=cap; this.cp=0; this.cw=0; this.bestp=0; //回溯搜索 this.Backtrack(1); for(i=0;i<n;i++){ System.out.println(Q[i].ID + ":" + bestx[i+1]); } return bestp; } public static void main(String[] args) throws IOException { int c=0,n=0,i=0; int[] p = new int[]{6,3,5,4,6}; int[] w = new int[]{2,2,6,5,4}; c=10; n=5; Knap k =new Knap(); int bestp = k.Knapsack(p, w, c, n); System.out.println(bestp); } }

你可能感兴趣的:(c,算法,String,search,Class,float)