日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

2012百度之星冬季赛第二场第二题 消去游戏I

發布時間:2024/4/17 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2012百度之星冬季赛第二场第二题 消去游戏I 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
2012百度之星冬季賽第二場第二題 消去游戲I

題目:

Alice和Bob又開始發明新游戲了,這回的名字叫消去游戲。

消去游戲的道具是一堆排成一行的積木,每個積木上面都有一個數字Ai。同時游戲也需要M個額外的數字Di,作為消去的判斷條件。當連續的K個積木數字相鄰的差值都相同并且和某個Di相等時,即構成一個長度為K等差為Di的等差數列時,他們可以拿去這一段積木,然后不改變剩余積木的順序,將他們合并。顯然,每次至少要消去2個積木。

現在他們希望知道,在一個給定局面下,能最多消去的積木數目。

Input

輸入第一行為T,表示有T組測試數據。

每組數據以兩個整數N,M開始,具體意義與描述相同。接著的一行包括N個整數,表示排成一行的積木數字Ai。接下來的一行是M個整數,即給定的消去差值Di。

1. 1 <= T <= 100

2. 1 <= N, M <= 300

3. -1 000 000 000 <= Ai, Di <= 1 000 000 000

Output

對每組數據,先輸出為第幾組數據,然后輸出最多能消去的積木數目。

Sample Input

3

3 1

1 2 3

1

3 2

1 2 4

1 2

4 2

1 3 4 3

1 2

Sample Output

Case 1: 3

Case 2: 2

Case 3: 4

Hint

第三組數據中,可以先消去第二個和第三個積木,然后消去剩下變為相鄰的兩個積木。注意不能直接消去第三個和第四個積木,因為它們的差值是-1,而不是1。

個人題解,結果公布前,暫時不保證能AC:????已AC

我的解法是DP的,為了便于思考,程序里面用了兩次DP,兩個其實可以合并的,因為狀態其實都是區間的消去情況。

首先,一次可以消去多個,這個條件必須轉化,不然很不利于狀態轉移,很快就可以發現,假如每次僅允許消去2個是不夠的,但是假如每次允許消去2個或者3個,其實就夠了,不管多長的區間總可以拆分為每次消去兩個和三個的組合。

????

然后第一個bool?dp[N][N],dp[i][j]表示區間[i,?j]可不可以消去

用map儲存允許的差值,用mp[d]==true來表示差值允許

a[i]表示原序列第i個數字

顯然

一、i>=j時,dp[i][j]=false

  感謝 ACdream的[scu]09p17(copy卡卡西)童鞋指正

  (哎,程序果然還有bug,過了只是運氣,我還是太連清了TAT)

  1. i == j時,此時區間為一個數,無法消去,dp[i][j]=false

  2. i >?j時,此時區間為空區間,dp[i][j]=true

二、i+1==j時,mp[a[j] - a[i]]

三、i+2==j時,a[j] - a[j-1] == a[j-1] - a[i] && mp[a[j] - a[j-1]]

四、i+2<j

  這時,根據上面得出的,每次刪兩個或三個這個條件,假如dp[i][j]要等于true,分為兩種情況

  1.區間由兩個可刪除區間組成

    也就是假如存在i<k<j使得 dp[i][k] && dp[k+1][j]

  2.區間是刪除了一些子區間后,剩下來的兩個或三個數字,正好可以消去

    ①剩下兩個可以消去,則這兩個必然是頭尾,否則在情況1里已經討論

      即dp[i+1][j-1] && mp[a[j] - a[i]]

    ②剩下三個可以消去,同①理,其中肯定有頭尾

      即存在i<k<j使得 a[j] - a[k] == a[k] - a[i] && dp[i+1][k-1] && dp[k+1][j-1] && mp[a[j] - a[k]]

這樣就討論完了,由于map的速度較慢,而且有很多的狀態為false,所以寫最后,優化下常數

狀態轉移較為復雜,就寫成記憶化搜索了,比較簡潔。

得到上面的dp[i][j]后

我們用ans[i]表示區間[0, i]最多能消去多少個,則

  ans[0]=0;

  ans[i] = Max(

        ans[i-1],                //a[i]沒有被消去

        Max(ans[j-1] + dp[j][i]?j-i+1:0)(0<j<i) //a[i]被消去,則肯定有區間[j, i]被消去,消去數為j-i+1,加上之前的區間[0, j-1]的最大消去數

      )

最終我們得到的ans[n-1]即為區間[0, n-1]的最大消去數,問題得以解決。第一個dp狀態數N^2,轉移費用由于枚舉k最大為N,時間復雜度為N^3, 不過在實際中,由于i>=j的狀態基本沒用到,加上一旦得出dp[i][j]=true就return的寫法,實際應該不容易達到這個上限。

ans這部分DP狀態數為N,轉移費用為N

綜合時間復雜度為O(n^3),N=300,還是有些緊張的。結果出來之前,個人覺得覺得有一定可能TLE。百度當天給出兩個√。

如果這題直接用dp[i][j]表示區間[i, j]的最大消去數應該也是可以的,最終答案為dp[0, n-1]

綜合上面兩個DP狀態轉移方程應該也是可以得到比較簡單的狀態轉移方程,不過木有地方測試啊。。。。

?

?

是不是還有可能用四邊形優化,求DP大神討論!!!!!

?

?

以下代碼:(百度之星比賽有代碼長度的分數,變量為了簡介并不與上面題解中一一對應,望諒解)

bug修改版

1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<map> 7 using namespace std; 8 const int N=310; 9 map<int,bool>mp; 10 int T,C,n,m,a[N],s[N],x; 11 char q[N][N]; 12 int dfs(int x,int y){ 13 char &ans=q[x][y]; 14 if(ans>=0) return ans; 15 if(y-x<0) return ans=1; 16 if(y==x) return ans=0; 17 if(y-x==1) return ans=mp[a[y]-a[x]]; 18 if(y-x==2) return ans=(a[y]-a[y-1]==a[y-1]-a[x] && mp[a[y-1]-a[x]]); 19 ans=0; 20 for(int i=x+1;i<y && !ans;i++){ 21 if(dfs(x,i) && dfs(i+1,y))ans=1; 22 if(a[i]-a[x] == a[y]-a[i] && dfs(x+1,i-1) && dfs(i+1,y-1) && mp[a[i]-a[x]]) 23 ans=1; 24 } 25 if(ans) return ans; 26 if(dfs(x+1,y-1) && mp[a[y]-a[x]]) ans=1; 27 return ans; 28 } 29 int main() 30 { 31 scanf("%d",&T); 32 while(T--){ 33 printf("Case %d: ",++C); 34 scanf("%d%d",&n,&m); 35 mp.clear(); 36 for(int i=0;i<n;i++)scanf("%d",a+i); 37 for(int i=0;i<m;i++){ 38 scanf("%d",&x); 39 mp[x]=true; 40 } 41 if(n==0){ 42 puts("0"); 43 continue; 44 } 45 memset(q,-1,sizeof q); 46 for(int i=1;i<n;i++){ 47 if(dfs(0,i)){ 48 s[i]=i+1; 49 continue; 50 } 51 s[i]=s[i-1]; 52 for(int j=1;j<i;j++)if(dfs(j,i) && s[j-1]+i-j+1>s[i]) 53 s[i]=s[j-1]+i-j+1; 54 } 55 printf("%d\n",s[n-1]); 56 } 57 return 0; 58 }

?

posted on 2012-12-24 18:27 混沌DM 閱讀(...) 評論(...) 編輯 收藏

轉載于:https://www.cnblogs.com/hundundm/archive/2012/12/24/2831444.html

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的2012百度之星冬季赛第二场第二题 消去游戏I的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。