1. 程式人生 > >2014 ACM/ICPC 西安邀請賽小記

2014 ACM/ICPC 西安邀請賽小記

看書看不下去於是開始寫總結了。

這是我們隊第一次參加ACM現場比賽,雖然是邀請賽啦,不過蒟蒻們可以去現場賽還是很開森啦,最後兩題第二水到了一個銅牌倒數。>_<

週六的熱身賽就開始防AK了,最後一道計算幾何別人都說寫起來會很麻煩,wmn敲完了模板之後還差十分鐘比賽結束,就棄療了。

不過我發現我還是看到題就會蒙的狀態,熱身賽前十幾分鍾我都是蒙的,做哪個題都是隊友定的,然後榜單出來刷出來後就跟著榜單做題了== 去年的網路賽我們就是這個樣子,之前一直以為現場賽看不到榜單還想著到時候怎麼數氣球呢。

熱身賽兩題都是2Y,一個是因為結尾多輸出了空格WA了,另一個是看錯了題把距離公式求錯TLE了。我可以說我第二天也看錯了題嗎== 不過幸好Debug Sample的時候發現了 So木有罰時。

不過熱身賽的B題真的是DFS爆搞麼?第二天問學長他說複雜度就是邊的個數,逐個判斷每條邊即可,可我總覺得複雜度是N! =。= 好吧我對複雜度太不敏感了,直接導致了第二天本來應該DP的題被我爆搞成了DFS徹底跑偏。

晚上看了看GCJ的一道數位DP的題解,之前一直對數位DP不太熟,So臨時惡補一下,可第二天正式賽的一道DP+位運算的題卻木有反應過來QAQ。

第二天就是正式賽,我覺得我看到滿頁滿頁英文的problem set還是蒙的== A題是簽到題,不過題幹很長,被我直接跳過,bxz老老實實地把那道題看完了。我看他們都從前往後翻題,我就從後往前翻,看到最後一題感覺有希望,就是BFS之類的,應該可以做出來。

比較坑的是B題,Sample有問題,到了很久很久以後Judge才改了題目。當初我問Judge “What is the exact meaning of Deadline in the Sample?”然後果真木有理我。果真提問應該問的具體一些的,我看後來有人問“Why does Doge travel to DP2 at time of 8?” Judge就回復了。

過了簽到題後我開始敲C,當然題目也不是我讀的,C就是按照題目給出的公式求一個矩陣,再跑一遍最短路。本地Sample除錯了好久,主要就是因為把題目輸出的量看錯了吧。提交了之後居然1Y,真心奇蹟,Dijkstra好久都木有寫了(其實也就是對著模板敲而已),而且我當時不太熟悉Dijsktra+優先佇列是怎麼寫的了,每次都是遍歷尋找最小的d[u],居然木有TLE。

可惜之後就木有再AC了。%>_<% D題是個構造題,我一看這種字串+考驗智商的構造就無從下手,於是就扔給了隊友,我開始看J題。J最後有70+隊伍AC,可惜我們不是其中之一。J先用BFS做個預處理,求出所有tunnel的出口到其餘的tunnel的入口的距離,BFS我居然也能寫出bug==當初弄模板的時候覺得BFS不常用就隨便copy了一段以前寫過的code,比賽時發現那段code不完全是標準的BFS,只好自己重頭寫。

然後我就栽進了DFS的坑裡。其實算一算也知道15!肯定會爆掉的,可熱身賽爆搞就過了啊==真後悔當初木有好好深究,熱身賽那一題就是找到一個存在的解既可,和我們這個要找出最優解不一樣。可我總覺得最壞情況下兩者複雜度差不多啊,難道是資料太弱了==?

第一次TLE了之後,我做了剪枝處理,然後就返回了WA。。。真是坑啊,然後我就又以為爆搞是可以過的,然後我的重點就變成了滿世界尋找為什麼WA。。。如果剪枝後返TLE我估計我都會聯想到DP去。 QAQ

期間聯想過用DP,感覺這種 travel each of the tunnels once and only once和TSP很像,可我不知道怎麼寫啊,運籌學裡學TSP的時候,狀態都用集合表示的,然後我怎麼寫個集合。。。?

比賽結束後和學弟討論了一下知道怎麼做了。事實上還是用DP,可以用二進位制數表示狀態,最多也就有2^15個狀態,肯定不會MLE。實際處理的時候可以將十進位制數map到二進位制數+位運算。

假設一共三個tunnel,狀態陣列標記為 pair<int,int>d[MAX];

MAX是二進位制數map的十進位制數,d[i].first是遍歷標記為1的tunnels的最短距離,d[i].second該狀態對應的出口。

d[1,1,0].first=min(d[0,1,0].first+dis[d[0,1,0].second][1],d[1,0,0].first+dis[d[1,0,0].second][2])

其中dis[x][y]表示從 tunnel x 的出口到 tunnel y 的入口的距離

然後對於具體的d[x],可以通過 

<span style="font-size:18px;">for(int i=0;i<15;i++)
{
	if((1<<i)&&x==1) 
	{
		int tmp=x-(1<<i);
		if(d[x].first<d[tmp].first+dis[d[tmp].second][m-i];//m is the number of tunnels
		{
			 d[x].first=d[tmp].first+dis[d[tmp].second][m-i];
			 d[x].second=m-i;						
		}
	}
}</span>

進行狀態轉移。

就是位運算啊,前幾天百度之星資格賽的那道字典樹剛寫過這個。。資格賽另一題是Bitonic TSP為神馬當時木有好好看=。=

邊界條件:

<span style="font-size:18px;">for(int i=0;i<m;i++)
{
	d[1<<i].first=0;
	d[1<<i].second=i+1;//the index starts from 1
}</span>


最後就可以直接打表了QAQ

<span style="font-size:18px;">for(int i=2;i<=m;i++)
{
	用 next_permutation() 列出i個1的情況下的所有排列。
	狀態轉移。
}</span>

d[1,1,1]就是最終結果。

感覺應該沒啥問題吧,啥時候有空就把這題寫一寫,我這反應的延遲是不是太長了一些 QAQ 放我回西工大交題去!╮(╯▽╰)╭

剩下的時間我們都卡在了這兩道題上,比賽結束後她們討論了一下D題感覺再改一個地方也可以AC的。

其實我們就算過了J題估計也是銅

比賽前的目標是一人一個氣球帶回家的~~~~(>_<)~~~~ ,本來覺得兩題肯定鐵牌了,比賽結束兩分鐘終榜就放出來了,因為敲鍵盤比較快,還可以那個銅,好開森啊~

不過說好的最佳女隊獎卻木有發,是因為女隊太少了麼。。。

期待以後有更精彩的表現!