藍橋杯演算法訓練——lift and throw
#include <iostream> #include <cmath> #include <cstring> using namespace std; #define M 50 struct People { int pos; bool lifted;//正在被舉著 bool lifting;//正在舉著別人 int lift;//舉著的是誰 int maxmove;//最大移動距離 int maxthrow;//最大拋距離 bool hasmoved;//是否移動過 bool haslifted;//是否舉過別人 //沒有必要加上是否拋過別人的標記,因為只能舉起別人一次 }p[3]; bool Pos[M];//數軸,作為標記是否某位置上有人 bool visit[10];//排序標記,有三個人且每個人有移動、舉起、丟擲三種狀態,共有9種操作 int Max=0;//記錄最大位置 void dfs(int k,int step) { int n = k / 3; //當前執行操作的人 int m = k % 3; //當前執行的動作 //move if(m==0) { if(p[n].lifted || p[n].lifting || p[n].hasmoved) return; int i=1; if(step == 9) i=p[n].maxmove;//最後一步,則直接向前移動最大距離 /*如果不是最後一步,那麼他也不必從他能移動的最靠後的距離開始搜尋 他只需要從 他的位置之前的 有人的位置 的前一個位置 開始搜尋即可 如果他後面沒人,那麼他走的距離只需要從1開始搜尋,不需要往後走,只需要往前走*/ else { for(int j=1;j<p[n].pos;j++) //從第一個位置到p[i]的當前位置遍歷 { if(Pos[j])//找p[i]前面有人的位置,以此來判斷移動距離 { int l = -(p[n].pos-j-1);//l為移動位置的 後一個位置 i= l<i?l:i; } } i = i > -p[n].maxmove ? i : -p[n].maxmove; //移動的距離不可以大於p[i]的最大移動距離 }//找出i---即最大移動多少步 for(;i <= p[n].maxmove; i++) { if(Pos[p[n].pos+i-1] || Pos[p[n].pos+i+1] || i==p[n].maxmove) //移動到的位置 的 前後有人,才可以進行舉起丟擲,才有意義 { if(p[n].pos+i >0 && !Pos[p[n].pos+i]) //不可以移動到數軸外,且移動的位置必須為空 { if(!i) continue;//i=0,表示不移動,進入下一個for迴圈 Pos[p[n].pos]=false;//當前位置置零 p[n].pos += i;//move i步 Pos[p[n].pos]=true;//move後的位置 置為1 p[n].hasmoved=true;//標記 Max= p[n].pos>Max ? p[n].pos : Max;//記錄最大位置 //向下一步 深搜 for(int j=0;j<9;j++) { if(!visit[j]) { visit[j]=true; dfs(j,step+1); //向下一步 深搜 visit[j]=false;//回溯 } } //回溯 Pos[p[n].pos]=false; p[n].pos -= i; Pos[p[n].pos]=true; p[n].hasmoved=false; } } } } //lift else if(m==1) { if(p[n].lifted || p[n].lifting || p[n].haslifted) return; for(int i=0;i<3;i++) //找旁邊的人,初始判斷條件為兩者距離為1 { if(abs(p[i].pos-p[n].pos) == 1) { if(p[i].lifted) continue;//如果這個人正被舉著,則不能重複舉起 //否者,標記相關資訊 p[n].haslifted=true; p[n].lifting=true; p[n].lift=i; p[i].lifted=true; int temp=p[i].pos; //臨時中間變數,以便回溯 Pos[p[i].pos]=false;//i被舉起,則位置p[i].pos為空 p[i].pos=p[n].pos;//p[i]的位置即為p[n]的位置 //如果被舉起的人i正在舉著別人,則i舉著的那個人的位置也要改變 if(p[i].lifting) { int j=p[i].lift;// j就是被i舉著的人 p[j].pos=p[i].pos; } //繼續搜尋 for(int j=0;j<9;j++) { if(!visit[j]) { visit[j]=true; dfs(j,step+1);//向下一步深搜 visit[j]=false; } } //回溯(將一切標記過的或者改動過的還原) p[n].haslifted=false; p[n].lifting=false; p[n].lift= -1; p[i].lifted=false; p[i].pos=temp;//臨時變數的作用即為 記下p[i]的原始位置,便於i還原 Pos[p[i].pos]=true; //p[i]舉著的人j也要記得還原為 :p[j]所被p[i]舉著的位置 if(p[i].lifting) { int j=p[i].lift;// j就是被i舉著的人 p[j].pos=p[i].pos; } } } } //throw else { if(!p[n].lifting || p[n].lifted) return; //如果這個人並沒有舉著別人,這或個人正被舉著,則退出 int i=1; if(step == 9) i=p[n].maxthrow;//最後一步,直接向前丟擲最大距離 else { for(int j=1;j<p[n].pos;j++) //從第一個位置到p[i]的當前位置遍歷 { if(Pos[j])//找p[i]前面有人的位置,以此來判斷丟擲距離 { int l=-(p[n].pos-j-1);//l為丟擲位置的 後一個位置 i=l<i?l:i; } } i= i> -p[n].maxthrow? i : -p[n].maxthrow; //丟擲的距離不可以大於p[i]的最大丟擲距離 }//找出i---即最大丟擲多少步 for( ;i <= p[n].maxthrow; i++) { if(Pos[p[n].pos+i-1] || Pos[p[n].pos+i+1] || i == p[n].maxthrow) //丟擲到的位置 的 前後為空,才有意義 { if(p[n].pos+i>0 && !Pos[p[n].pos+i]) //不可以丟擲到數軸外,且丟擲所到的位置必須為空 { int j=p[n].lift;//j為要被丟擲的(即n舉著的)人 p[j].pos += i;//j 被throw i步 Pos[p[j].pos]=true;//throw後的位置 置為1 p[n].lifting=false;//標記 p[n].lift = -1; p[j].lifted=false;//丟擲後即為不再是被舉起狀態 Max= p[j].pos>Max ? p[j].pos : Max;//記錄最大位置 //若被丟擲的j的頭頂上還舉著人 if(p[j].lifting) { int k=p[j].lift;//k為被j舉著的人 p[k].pos=p[j].pos;//k的位置與j位置同步 } //向下一步 深搜 for(int q=0;q<9;q++) { if(q == k) continue;// if(!visit[q]) { visit[q]=true; dfs(q,step+1); //向下一步 深搜 visit[q]=false;//回溯 } } //回溯 Pos[p[j].pos]=false; p[j].pos -= i; p[j].lifted=true; p[n].lift=j; p[n].lifting=true; if(p[j].lifting) { int k=p[j].lift; p[k].pos=p[j].pos; } } } } } } int main() { memset(Pos, false, sizeof(Pos)); memset(visit, false, sizeof(visit)); //輸入 for(int i = 0; i < 3; i++) { cin >> p[i].pos >> p[i].maxmove >> p[i].maxthrow; p[i].lifted = p[i].lifting = p[i].hasmoved = p[i].haslifted = false; p[i].lift = -1; Pos[p[i].pos] = true; } //深搜 for(int i = 0; i < 9; i++) { //一個合法的第一步,不可能是拋。必須先移動或者舉起別人 if((i % 3) != 2) { visit[i] = true; dfs(i, 1); visit[i] = false;//回溯 } } //結果 cout << Max << endl; return 0; }
相關推薦
藍橋杯 演算法訓練 Lift and Throw
問題描述 給定一條標有整點(1, 2, 3, …)的射線. 定義兩個點之間的距離為其下標之差的絕對值. Laharl, Etna, Flonne一開始在這條射線上不同的三個點, 他們希望其中某個人能夠到達下標最大的點. 每個角色只
藍橋杯演算法訓練——lift and throw
#include <iostream> #include <cmath> #include <cstring> using namespace std; #define M 50 struct People { int pos;
演算法-藍橋杯-演算法訓練 Lift and Throw (C++)
1 引言 吃完飯,繼續,今天的目標是10篇,然後去看《演算法》和課外書。2 題目問題描述 給定一條標有整點(1, 2, 3, ...)的射線. 定義兩個點之間的距離為其下標之差的絕對值. Laharl, Etna, Flonne一開始在這條射線上不同的三個點, 他們
演算法訓練 Lift and Throw (DFS && 位運算)
問題描述 給定一條標有整點(1, 2, 3, …)的射線. 定義兩個點之間的距離為其下標之差的絕對值. Laharl, Etna, Flonne一開始在這條射線上不同的三個點, 他們希望其中某個人能夠到達下標最大的點. 每個角色只能進行下面的3
藍橋杯 演算法訓練 字母圖形
問題描述 利用字母可以組成一些美麗的圖形,下面給出了一個例子: ABCDEFG BABCDEF CBABCDE DCBABCD EDCBABC 這是一個5行7列的圖形,請找出這個圖形的規律,並輸出一個n行m列的圖形。 輸入格式 輸入一行
藍橋杯 演算法訓練 區間k大數查詢
明明是一個水題卻wrong answer了很多遍。。 還是因為對最基礎的氣泡排序概念不清。蠢死算了。 這下終於搞清楚了。 問題描述 給定一個序列,每次詢問序列中第l個數到第r個數中第K大的數是哪個。 輸入格式 第一行包含一個數
藍橋杯-演算法訓練 未名湖邊的煩惱 (遞迴)
演算法訓練 未名湖邊的煩惱 時間限制:1.0s 記憶體限制:256.0MB 問題描述 每年冬天,北大
[藍橋杯][演算法訓練VIP]猴子分蘋果
題目描述 秋天到了,n只猴子採摘了一大堆蘋果放到山洞裡,約定第二天平分。這些猴子很崇拜猴王孫悟空,所以都想給他留一些蘋果。第一隻猴子悄悄來到山洞,把蘋果平均分成n份,把剩下的m個蘋果吃了,然後藏起來一份,最後把剩下的蘋果重新合在一起。這些猴子依次悄悄來到山洞,都做同樣的操作,恰好每次
藍橋杯演算法訓練 最大最小公倍數
時間限制:1.0s 記憶體限制:256.0MB 問題描述 已知一個正整數N,問從1~N-1中任選出三個數,他們的最小公倍數最大可以為多少。 輸入格式 輸入一個正整數N。 輸出格式 輸出一個整數,表示你找到的最小公倍數。 樣例輸入 9 樣例輸出
藍橋杯 演算法訓練 ALGO-81 動態陣列使用
演算法訓練 動態陣列使用 時間限制:1.0s 記憶體限制:512.0MB 從鍵盤讀入n個整數,使用動態陣列儲存所讀入的整數,並計算它們的和與平均值分別輸出。要求儘可能使用函式實現程式程式碼。平均值為小數的只保留其整數部分。 樣例輸入: 5 3 4 0 0 2 樣例輸出: 9 1 樣例
藍橋杯 演算法訓練 ALGO-122 未名湖邊的煩惱 遞迴 遞推
演算法訓練 未名湖邊的煩惱 時間限制:1.0s 記憶體限制:256.0MB 問題描述 每年冬天,北大未名湖上都是滑冰的好地方。北大體育組準備了許多冰鞋,可是人太多了,每天下午收工後,常常一雙冰鞋都不剩。 每天早上,租鞋視窗都會排起長龍,假設有還鞋的m個,有需要租鞋的n個。現在
藍橋杯 演算法訓練 ALGO-116 最大的算式 動態規劃 資源分配型別(最大乘積)
演算法訓練 最大的算式 時間限制:1.0s 記憶體限制:256.0MB 問題描述 題目很簡單,給出N個數字,不改變它們的相對位置,在中間加入K個乘號和N-K-1個加號,(括號隨便加)使最終結果儘量大。因為乘號和加號一共就是N-1個了,所以恰好每兩個相鄰數字之間都有一個符號。例如:
藍橋杯 演算法訓練 ALGO-101 圖形顯示 迴圈語句
演算法訓練 圖形顯示 時間限制:1.0s 記憶體限制:512.0MB 問題描述 編寫一個程式,首先輸入一個整數,例如5,然後在螢幕上顯示如下的圖形(5表示行數): * * * * * * * * * * * * * * * 分析:第一行輸出n個星號,
藍橋杯 演算法訓練 ALGO-97 排序 迴圈語句
演算法訓練 排序 時間限制:1.0s 記憶體限制:512.0MB 問題描述 編寫一個程式,輸入3個整數,然後程式將對這三個整數按照從大到小進行排列。 輸入格式:輸入只有一行,即三個整數,中間用空格隔開。 輸出格式:輸出只有一行,即排序後的結果。 輸入輸出樣例 樣例輸入
藍橋杯 演算法訓練 ALGO-95 2的次冪表示
演算法訓練 2的次冪表示 時間限制:1.0s 記憶體限制:512.0MB 問題描述 任何一個正整數都可以用2進製表示,例如:137的2進製表示為10001001。 將這種2進製表示寫成2的次冪的和的形式,令次冪高的排在前面,可得到如下表達式:137=27+23+2^0 現
藍橋杯 演算法訓練 ALGO-92 字首表示式 字元操作 數學知識
演算法訓練 字首表示式 時間限制:1.0s 記憶體限制:512.0MB 提交此題 問題描述 編寫一個程式,以字串方式輸入一個字首表示式,然後計算它的值。輸入格式為:“運算子 物件1 物件2”,其中,運算子為“+”(加法)、“-”(減法)、“*”(乘法)或“/”(除法),運算物件為
藍橋杯 演算法訓練 ALGO-91 Anagrams問題 陣列運算 字元操作
演算法訓練 Anagrams問題 時間限制:1.0s 記憶體限制:512.0MB 提交此題 問題描述 Anagrams指的是具有如下特性的兩個單詞:在這兩個單詞當中,每一個英文字母(不區分大小寫)所出現的次數都是相同的。例如,“Unclear”和“Nuclear”、“Rimon”
藍橋杯 演算法訓練 ALGO-90 出現次數最多的整數 陣列運算
演算法訓練 出現次數最多的整數 時間限制:1.0s 記憶體限制:512.0MB 問題描述 編寫一個程式,讀入一組整數,這組整數是按照從小到大的順序排列的,它們的個數N也是由使用者輸入的,最多不會超過20。然後程式將對這個陣列進行統計,把出現次數最多的那個陣列元素值打印出來。
藍橋杯 演算法訓練 ALGO-87 字串統計
演算法訓練 字串統計 時間限制:1.0s 記憶體限制:512.0MB 問題描述 給定一個長度為n的字串S,還有一個數字L,統計長度大於等於L的出現次數最多的子串(不同的出現可以相交),如果有多個,輸出最長的,如果仍然有多個,輸出第一次出現最早的。 輸入格式 第一行一個數字L。