1. 程式人生 > >藍橋杯演算法訓練——lift and throw

藍橋杯演算法訓練——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。