數字成環演算法
㈠ 用java編程:輸入1~20的整數n,把從1到n的n個整數擺成環,使得該環上任意
不用了,這個是一個常規演算法題,早就有標准代碼了
publicclassPrimeTest{
//判斷某整數是不是質數
publicstaticbooleanisp(intn){
for(inti=2;i<Math.sqrt(n)+1;i++){
if(n%i==0){
顫頌首returnfalse;
}
}
returntrue;
}
publicstaticintn=20;
publicstaticboolean[]vis=newboolean[n+1];//存儲某數是否被使用
publicstaticint[]arr=newint[n+1];//存放數列
publicstaticvoiddfs(intcur){
if(cur==n+1&&isp(arr[1]+arr[n])&&櫻虧arr[1]==1){//如果最後一個數放進去了,並且最後一個數和第一個的和為質數,並且第一個數是1(因為我們只輸出開頭是1的,避免重復)
for(inti=1;i<=n;i++){//列印出數列
System.out.print(arr[i]+",");
}
System.out.println();
}else{
for(inti=1;i<=n;i++){//嘗試放置每個數i
if(!vis[i]&&isp(i+arr[cur-1])){//如果這個數沒有被使用,並且與前一個數的和是質數
vis[i]=true;//標明這個數被使用
arr[cur]=i;//將這個數加入隊列
茄數dfs(cur+1);//求下一個數
vis[i]=false;//取消這個數
}
}
}
}
publicstaticvoidmain(String[]args){
arr[0]=0;
for(inti=0;i<=n;i++){
vis[i]=false;
}
dfs(1);
}
}
1,2,3,4,7,6,5,8,9,10,13,16,15,14,17,20,11,12,19,18,
1,2,3,4,7,6,5,8,9,10,13,16,15,14,17,20,11,18,19,12,
1,2,3,4,7,6,5,8,9,10,13,18,19,12,11,20,17,14,15,16,
1,2,3,4,7,6,5,8,9,10,19,12,11,20,17,14,15,16,13,18,
1,2,3,4,7,6,5,8,9,10,19,18,13,16,15,14,17,20,11,12,
1,2,3,4,7,6,5,8,9,14,15,16,13,10,19,12,17,20,11,18,
1,2,3,4,7,6,5,8,9,14,15,16,13,10,19,18,11,20,17,12,
1,2,3,4,7,6,5,8,9,14,15,16,13,18,11,20,17,12,19,10,
1,2,3,4,7,6,5,8,9,20,11,12,17,14,15,16,13,10,19,18,
1,2,3,4,7,6,5,8,9,20,11,12,17,14,15,16,13,18,19,10,
1,2,3,4,7,6,5,8,9,20,11,18,13,10,19,12,17,14,15,16,
1,2,3,4,7,6,5,8,9,20,11,18,13,16,15,14,17,12,19,10,
底下還有好幾頁
㈡ 環和演算法是什麼
頂點是兩個圖的頂點的並集,但是邊要去掉相同的邊,也即是兩個圖是沒有共同的邊。
㈢ 貪心演算法:最小生成樹,霍夫曼編碼
連通圖: 在無向圖中,若任意兩個頂點vi與vj都有路徑相通,則稱該無向圖為連通圖。
強連通圖(Strongly Connected Graph) 是指在有向圖G中,如果對於每一對vi、vj,vi≠vj,從vi到vj和從vj到vi都存在路徑,則稱G是強連通圖。
連通網: 在連通圖中,若圖的邊具有一定的意義,每一條邊都對應著一個數,稱為權;權代表著連接連個頂點的代價,稱這種連通圖叫做連通網。
生成樹: 一個連通圖的生成樹是指一個連通子圖,它含有圖中全部n個頂點,但只有足以構成一棵樹的n-1條邊。一顆有n個頂點的生成樹有且僅有n-1條邊,如果生成樹中再添加一條邊,則必定成環。
最小生成樹: 在連通網的所有生成樹中,所有邊的代價和最小的生成樹,稱為最小生成樹。
示例:
分別使用 Kruskal演算法 和 Prim演算法 ,找出下圖的最小生成樹。
使用變長編碼表對源符號(如文件中的一個字母)進行編碼,其中變長編碼表是通過一種評估來源符號出現機率的方法得到的,出現機率高的字母使用較短的編碼,反之出現機率低的則使用較長的編碼,這便使編碼之後的字元串的平均長度、期望值降低,從而達到無損壓縮數據的目的。
具體步驟
1.將信源符號的概率按減小的順序排隊。
2.把兩個最小的概率相加,並繼續這一步驟,始終將較高的概率分支放在右邊,直到最後變成概率1。
3.畫出由概率1處到每個信源符號的路徑,順序記下沿路徑的0和1,所得就是該符號的霍夫曼碼字。
4.將每對組合的左邊一個指定為0,右邊一個指定為1(或相反)。
示例:
假設字元a,b,c,d,e出現的概率分別為1/2,1/4,1/8,1/16,1/16。
1.求出各字元哈夫曼編碼表。
2.假設一個文件有1,000,000個字元,求出編碼之後文件的位元組長度。
A:0
B:10
C:110
D:1110
E:1111
a所佔長度l1為:(1,000,000/2) 1
b所佔長度l2為:(1,000,000/4) 2
c所佔長度l3為:(1,000,000/8) 3
d所佔長度l4為:(1,000,000/16) 4
e所佔長度l5為:(1,000,000/16)*4
文件的總長度l = l1 + l2 + l3 + l4 + l5 = 1875000
㈣ 判環演算法以及鏈表常見演算法題
由於涉及到Floyd判環演算法,故先簡單闡述一下Floyd判環演算法原理。
Floyd判環演算法
演算法原理:設置兩個指針同時從頭結點向後訪問(當兩指針後繼不為null),不過兩指針的訪問速度不一致,第一個指針每次後移一個元素,第二個指針每次後移兩個元素。若鏈表成環,則兩指針在某一時刻必然相遇,否則不相遇
計算環長度:
當指針相遇時,保持其中一個指針不動,另一個指針向後訪問,每次後移一個單位,當兩指針再次相遇時,該指針移動的單位即為環的長度
計算環起始節點:
第一次相遇後,慢指針從頭結點向後訪問,快指針從相遇點同時向後訪問,不過兩者的移動速度都為1,當兩者再次相遇時,該緩伍相遇的節點即為環的起始節點,分析如下:
如下圖所示,假設h為鏈表頭結點,p為兩指針第一次相遇節點,m為頭結點到起始節點走過的路程(經過的節點個數),n為環起始節點到p的路程,則對於第一次相遇有:
慢指針走過的路程:s=m+n+a C
快指針走過的路程:2 s=m+n+b C
a,b分別表示兩指針相遇前第一次經過p點後繞環的圈數,C表示環的長度,由於快指針的速度是慢指針的兩倍,時間一樣,故快指針走過的路程是慢指針的兩倍。
兩式相減有s=(b-a) C=m+n+a*C
故m+n恰為環長度的整數倍
慢指針從頭結點到起始節點走了m,由於同時同速伍哪余度快指針也走了m,而移動前快指針距起始節點距離為n,m+n恰為環長度的整數倍,故快指針移動m後也到了起始節點,即此時相遇點為起始節點
2.1判斷鏈表是否以null結尾,是否包含環
2.2判斷給定的鏈表是否以null結束。如果鏈表中存在環,找到環的起始節點
2.3判斷鏈表是否存在環,若存在,則返回環的長度,否則返回0
3.將一個循環鏈表變成兩個循環鏈表
4.有序鏈表中插入一個節點
5.1鏈表逆置
5.2逐對逆置鏈表,假如初始鏈表為1 2 3 4 x,逐對逆置後為2 1 4 3 x
6.判斷兩個鏈表是否相交成為一個單鏈表,若相交,得出兩鏈表的相交節點
7.尋找鏈表的中間節點:設置兩個指針,第一個指針的移動速度是第二個指針的兩倍,當第一個指針到達表尾,第二個指針即指向中間節點
8.檢查鏈表長度是奇數還是偶數,每腔滾次後移兩個元素,返回1表示奇數,返回0表示偶數
9.合並兩個有序鏈表
10.從表尾開始輸出鏈表
㈤ 急!一個Java題(在下圖中的九個點上,空出中間的點...)
import javax.swing.JFrame ;
import javax.swing.JPanel ;
import java.awt.Graphics ;
import java.awt.BorderLayout ;
import java.awt.Color ;
import java.util.ArrayList ;
public class MobileSorter extends JFrame {
//上邊距
public static final int TOP_SPA = 100 ;
//左邊距
public static final int LEFT_SPA = 100 ;
public static void main(String args[]) {
JFrame.(true) ;
MobileSorter ms = new MobileSorter() ;
ms.setVisible(true) ;
}
public MobileSorter() {
//設置窗體大小
this.setSize(400 ,400) ;
//new出組件
MyPanel p = new MyPanel() ;
//布置窗體
this.setLayout(new BorderLayout()) ;
this.add(p ,BorderLayout.CENTER) ;
//啟動線程
Thread t = new Thread(p) ;
t.start() ;
}
}
class MyPanel extends JPanel implements Runnable {
//存儲圓數據的數組
private ArrayList ca = new ArrayList(9);
/**
* 中心圓
*/
private Circle cCenter = null ;
public MyPanel() {
init() ;
}
public void paint(Graphics g) {
//畫與5號位的斜連接線
for (int i = 0; i<9; i++) {
if (i == 4) continue ;
Circle.drawLine(g ,(Circle)ca.get(4) ,(Circle) ca.get(i)) ;
}
//垂直和橫線和豎線
g.setColor(Color.BLACK) ;
for (int i = 0; i<9; i++)
for (int j = 0; j<9; j++)
if (i != j && i < j)
if (j - i ==3 || (i + 1 == j && j%3 != 0))
Circle.drawLine(g , (Circle) ca.get(i) ,(Circle) ca.get(j)) ;
/** 畫圓 */
for (int i = 0; i<9; i++)
((Circle) ca.get(i)).drawMe(g) ;
}
/**
* 初始化
*/
public void init() {
//創建圓
for (int i = 1; i<10; i++)
this.ca.add(new Circle(i)) ;
//生成圓內的數
int[] n = new int[9] ;
for (int i = 0; i<n.length; ) {
int c ;
c = (int)(Math.random() * 8) + 1 ;
boolean isRepeat = false ;
for (int j = 0; j<i; j++)
if (n[j] == c) {
isRepeat = true ;
break ;
}
if (isRepeat) continue ;
if (i == 4) i ++ ;
((Circle)this.ca.get(i)).setNum(c) ;
n[i] = c ;
i ++ ;
}
}
/**
* 線程
*/
public void run() {
int oPos = 0 ; //值為1的圓的標號
int sPos ; //值為1的圓的下一個圓的標號
int ePos ; //終端圓標號
int cPos = 0 ; //操作圓標號
cCenter = (Circle)this.ca.get(4) ; //中心圓
//找出圓內數字的1的圓
for (int i = 0; i<this.ca.size(); i++)
if (((Circle)this.ca.get(i)).getNum() == 1) {
oPos = i ;
break ;
}
sPos = Circle.getNextDeasil(oPos) ;
ePos = oPos ;
while (true) {
cPos = sPos ;
while (true) {
Circle c = (Circle)this.ca.get(cPos) ;
Circle n = (Circle)this.ca.get(Circle.getNextDeasil(cPos)) ;
checkSwap(c ,n) ;
cPos = Circle.getNextDeasil(cPos) ;
if(ePos == Circle.getNextDeasil(cPos)) {
ePos = cPos ;
break ;
}
}
if (ePos == Circle.getNextDeasil(sPos)) {
System.out.println ("OVER!") ;
break ;
}
}
}
/**
* 延遲
*/
private void animation() {
this.repaint() ;
try { Thread.sleep(1000) ;}catch (Exception ex) { }
}
/**
* 交換
*/
private void checkSwap(Circle c ,Circle n) {
int cNum = c.getNum() ;
int nNum = n.getNum() ;
if (cNum > nNum) {
cCenter.setNum(n.getNum()) ;
n.setNum(0) ;
this.animation() ;
n.setNum(c.getNum()) ;
c.setNum(0) ;
this.animation() ;
c.setNum(cCenter.getNum()) ;
cCenter.setNum(0) ;
this.animation() ;
}
}
}
class Circle {
/**
* 各圓之間的間距
*/
public static final int CIR_SPA_BET = 60 ;
/**
* 圓的直徑
*/
public static final int CIR_WD = 30 ;
/**
* 圓的標號 ,1-9
*/
private int pos ;
/**
* 圓的左上角x坐標
*/
private int x ;
/**
* 圓的左上角y坐標
*/
private int y ;
/**
* 圓內的數
*/
private int num ;
public Circle(int pos) {
this.pos = pos ;
this.x = MobileSorter.LEFT_SPA + (pos-1) % 3 * CIR_SPA_BET ;
this.y = MobileSorter.TOP_SPA + (pos-1) / 3 * CIR_SPA_BET ;
}
/**
* 畫圓與圓中的數字
*/
public void drawMe(Graphics g) {
//圓
g.setColor(Color.BLACK) ;
g.fillOval(x ,y ,CIR_WD ,CIR_WD) ;
//數字
g.setColor(Color.WHITE) ;
if (num != 0)
g.drawString(String.valueOf(num)
,x + CIR_WD / 2 - 3 ,y + CIR_WD / 2 + 5) ;
else
g.drawString("空"
,x + CIR_WD / 2 - 3 ,y + CIR_WD / 2 + 5) ;
}
/**
* 畫兩個圓之間的連接線
*/
public static void drawLine(Graphics g ,Circle a , Circle b) {
g.drawLine(a.getX() + Circle.CIR_WD / 2
,a.getY() + Circle.CIR_WD / 2
,b.getX() + Circle.CIR_WD / 2
,b.getY()+ Circle.CIR_WD / 2) ;
}
public void setNum(int num) {
this.num = num ;
}
public int getX() {
return x ;
}
public int getY() {
return y ;
}
public int getPos() {
return pos ;
}
public int getNum() {
return num ;
}
public static int getNextDeasil(int pos) {
if (pos >=0 && pos <=8 && pos != 4) {
if (pos == 0)
return 1 ;
else if (pos == 1)
return 2 ;
else if (pos == 2)
return 5 ;
else if (pos == 3)
return 0 ;
else if (pos == 5)
return 8 ;
else if (pos == 6)
return 3 ;
else if (pos == 7)
return 6 ;
else if (pos == 8)
return 7 ;
}
return -1 ;
}
/**
* 根據順時針方向返回下個圓的標號
*/
public int getNextDeasil() {
if (pos >=0 && pos <=8 && pos != 4) {
if (pos == 0)
return 1 ;
else if (pos == 1)
return 2 ;
else if (pos == 2)
return 5 ;
else if (pos == 3)
return 0 ;
else if (pos == 5)
return 8 ;
else if (pos == 6)
return 3 ;
else if (pos == 7)
return 6 ;
else if (pos == 8)
return 7 ;
}
return -1 ;
}
}
㈥ 回溯演算法 求1-20這2個數擺成環,要求相鄰的兩個數的和是素數。我的代碼如下:沒有語法錯誤,但是死循環
intsearch(int)、intprint()、intmain()這三個函數名前都有返回值類型符,但函數體內卻都沒有返回語句。你也寫復雜了,下面的代碼就可以了:
#include"stdio.h"
intprime(intn){
inti;
if(n>2&&!(n&1)||n<2)
return0;
for(i=3;i*i<=n;i+=2)
if(!(n%i))
return0;
return1;
}
intmain(void){
inti,j;
for(i=1;i<20;i++)
if(prime(j=(i<<1)+1))
printf("%2d+%2d=%2d ",i,i+1,j);
return0;
}
㈦ 排列組合五組圍成環且每組的兩個人必須靠在一起
都是錯的.
正確應為 A22*A44
甲乙歲配兩人隨即排A22
剩下甲乎搏指乙(看做一人)銀中丙丁戊A44
第二種是從五人中隨即選兩人站在一起的解法 甲乙已確定,無需再選取組合了