Csp S 2020 T4 貪吃蛇 題解

2021-10-10 21:11:17 字數 3920 閱讀 9351

這道題我調了好久…細節非常多。

首先,看完題目後,可以發現這是一道博弈問題。

那麼接下來,我們假設最強蛇為 x

xx ,最弱蛇為 y

yy ,那麼這裡就有兩個結論:

如果 x

xx 吃了 y

yy 不是最弱的蛇,則 x

xx 必吃 y

yy 。

證明:假設當前第二強的蛇為 a

aa ,第二弱的蛇為 b

bb ,那麼 x

>

a>

b>y,

x−

y>

bx>a>b>y,x-y>b

x>

a>

b>y,

x−y>

b ,那麼假設 x

xx 吃了 y

yy 之後變成了 z

zz ,那麼此時有 z

>

bz>b

z>

b (這裡 z

zz 和 a

aa 的大小不能確定,因為有可能最強蛇吃掉最弱蛇還是最強蛇) ,如果 z

>

az>a

z>

a ,那麼 z

zz 還是最強蛇,所以 x

xx 肯定要吃掉 y

yy ,畢竟吃完後選擇權還在 x

xx 手上;如果 a

>

za>z

a>

z ,那麼 a

>z=

x−

y>

ba>z=x-y>b

a>z=

x−y>

b ,由於 x

>

a>

b>

yx>a>b>y

x>

a>

b>

y ,假設 a

aa 吃了 b

bb 之後變成了 c

cc ,那麼有 z

>

cz>c

z>

c 。因此,如果 c

cc 不死,那麼 z

zz 不會死,可以放心吃;否則,a

aa 為了活命,不能吃掉 b

bb 變成 c

cc ,因此此時 x

xx 仍然可以吃 y

yy 。

所以綜上,如果 x

xx 吃了 y

yy 不是最弱的蛇,則 x

xx 必吃 y

yy 。

如果 x

xx 吃了 y

yy 之後變成最弱的蛇了,那麼要不要吃呢?

此時,我們就不能看 x

xx 的選擇了,而要看下一條蛇的選擇。此處令 f

ff 為第二強的蛇,g

gg 為第三強的蛇,如果 x

xx 吃了 y

yy 變成 z

zz ,那麼 z

zz 能不能活看 f

ff 。如果 f

ff 吃了 z

zz ,那麼 x

xx 不能吃 y

yy ;否則,f

ff 不吃 z

zz 那麼 x

xx 可以吃 y

yy。那麼 f

ff 吃不吃又是看誰的呢?假設 f

ff 吃掉最弱蛇不是最弱蛇,由上述結論 f

ff 可以吃最弱蛇;否則,這個問題就變成了 「如果 f

ff 吃了最弱蛇後變成了最弱蛇,那麼要不要吃呢?」此時,我們驚喜的發現這個問題變成了乙個遞迴問題!那麼 f

ff 吃不吃完全看 g

gg 的選擇, 可以推出:g

gg 吃 f

ff 不吃 x

xx 吃,g

gg 不吃 f

ff 吃 x

xx 不吃。因此,我們在程式中不斷遞迴就好,假設當前第 k

kk 強的蛇吃,那麼 k−1

k-1k−

1 不吃,k−2

k-2k−

2 吃,k−3

k-3k−

3 不吃…直到第 1 強的蛇為止。

因此思路就是:先執行結論 1 ,無法執行時根據結論 2 的結果判斷是否還能再吃 1 次,最後輸出答案。

而由於原序列已經有序,因此這道題我們可使用兩個雙端佇列 q1,

q2

q1,q2

q1,q

2 維護。首先所有蛇入隊 q1q1

q1,執行結論 1 時所有生成的新蛇從對頭入隊 q2q2

q2,每一次取出最大值和最小值判斷。當沒辦法再執行結論 1 時,跳至結論 2 遞迴再看一次能否再吃 1 條。這樣,時間複雜度為 o(t

n)

o(tn)

o(tn

) ,可以通過此題。

上**:

#include

using

namespace std;

const

int maxn=

1e6+10;

int t,n,a[maxn]

,q1[maxn][2

],q2[maxn][2

],l1,l2,r1,r2,ans;

//ans=被吃了幾條蛇

//q1[i][0]=q2[i][0]=值,q1[i][1]=q2[i][1]=編號

struct node

;int

read()

return sum;

}node get_max()

//取出最大值}if

(l1<=r1)

else

if(q1[r1][0

]==sum&&q1[r1][1

]>id)}if

(flag==

1) r1--

;else r2--

;return

(node);}

node get_min()

//取出最小值}if

(l1<=r1)

else

if(q1[l1][0

]==sum&&q1[l1][1

](flag==

1) l1++

;else l2++

;return

(node);}

void

solve1()

//結論 1

else

continue;}

else

//不能吃

else

if(z.flag==1)

else

if(y.flag==1)

else

//塞回佇列裡面

return;}

}}bool

slove2

(int last)

//結論 2

else

if(l1<=r1&&

(x.sum-y.sum]||

(x.sum-y.sum==q1[l1][0

]&&q1[l1][1

]>x.id)))

else

return

!slove2

(last-1)

;//遞迴實現 }}

intmain()

else

} l1=

1;r1=

0;l2=n+

1;r2=n;

for(

int i=

1;i<=n;i++

) q1[

++r1][0

]=a[i]

;for

(int i=

1;i<=n;i++

) q1[i][1

]=i;

solve1()

;if(slove2

(n-ans)

) ans++

;//根據結論 2 看看能不能再吃一條

cout<"\n"

;//輸出存活蛇

}return0;

}

CSP S2020 貪吃蛇 題解

題意分析 給出乙個序列,以權值為第一關鍵字,編號為第二關鍵字單調遞增,每次操作讓最大元素的權值減去最小元素的權值,刪除最小元素,將最大元素插回序列並維護單調性,且每次操作要使當前最大元素操作後不必定被刪除,求最後最少能剩下幾個元素。思路分析 設原序列為 為了方便表述,本文對序列 中的元素的大小比較均...

利用Canvas js實現貪吃蛇 4

將貪吃蛇改造成物件導向,類似外掛程式的東西。過程中,要把握好this的指向,因為這個,除錯了好大會 將randfood進行了修正,新增了乙個配置引數與預設引數合併方法,其他的都還是一樣的。html 沒有改,在第一篇文章裡 附上 function tanchishe options this.sett...

用原生Canvas寫貪吃蛇及問題解決

為了學習canvas,寫了這個小遊戲貪吃蛇供自己和大家學習 github play on 遊戲截圖 前言 為了方便載入轉移,我把整個js都寫在了html裡,為了方便閱讀,將函式結構在html裡清晰地分開,並在 裡有足夠注釋。函式結構如下 script definations global snake...