hdu5693 D Game
阿新 • • 發佈:2018-01-20
review panel play get ace 字符 tom 數據 input
今天,它發明了一個遊戲:D遊戲。
度度熊的英文並不是很高明,所以這裏的D,沒什麽高深的含義,只是代指等差數列[(等差數列百科)](http://baike.baidu.com/view/62268.htm)中的公差D。
這個遊戲是這樣的,首先度度熊擁有一個公差集合{D} ,然後它依次寫下N個數字排成一行。遊戲規則很簡單:
1. 在當前剩下的有序數組中選擇X(X≥2) 個連續數字;
2. 檢查1選擇的X個數字是否構成等差數列,且公差 d∈{D};
3. 如果2滿足,可以在數組中刪除這X個數字;
4. 重復 1−3 步,直到無法刪除更多數字。
度度熊最多能刪掉多少個數字,如果它足夠聰明的話?
每組數據以兩個整數 N,M 開始 。接著的一行包括 N 個整數,表示排成一行的有序數組 Ai。接下來的一行是 M 個整數,即給定的公差集合 Di。
1≤N,M≤300
−1 000 000 000≤Ai,Di≤1 000 000 000
鏈接
D Game
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 883 Accepted Submission(s): 317
今天,它發明了一個遊戲:D遊戲。
度度熊的英文並不是很高明,所以這裏的D,沒什麽高深的含義,只是代指等差數列[(等差數列百科)](http://baike.baidu.com/view/62268.htm)中的公差D。
這個遊戲是這樣的,首先度度熊擁有一個公差集合{D}
1. 在當前剩下的有序數組中選擇X(X≥2) 個連續數字;
2. 檢查1選擇的X個數字是否構成等差數列,且公差 d∈{D};
3. 如果2滿足,可以在數組中刪除這X個數字;
4. 重復 1−3 步,直到無法刪除更多數字。
度度熊最多能刪掉多少個數字,如果它足夠聰明的話?
Input 第一行一個整數T,表示T(1≤T≤100) 組數據。
每組數據以兩個整數 N,M 開始 。接著的一行包括 N 個整數,表示排成一行的有序數組 Ai。接下來的一行是 M 個整數,即給定的公差集合 Di。
1≤N,M≤300
−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 3 2 4
Source 2016"百度之星" - 初賽(Astar Round2A)
Recommend wange2014 這個問題可以看出是dp,但如果用f[i][j]表示i到j能刪除多少個似乎並不好轉移,我們可以轉變一下思路,f[i][j]表示i到j能否全部刪除,假如我們求出了這個,我們可以通過一個簡單的dp得到所有數一共最多刪多少個。 因為要連續刪除x>=2個數字,事實上,刪4個和分兩次刪,各刪2個,刪5個分兩次,分別刪2,3個是一樣的,2和3可以湊出所有的數字,於是我們只需要考慮通過刪2個或者3個來轉移即可。 我們將問題分為兩種情況,最後一次刪除是否同時刪除了左右端點,如果不是,那麽我們一定可以將原區間分為兩段,把問題分為兩個更小的子問題,通過區間dp解決,如果是,那麽我們要分為兩種情況,刪2個或者刪3個,如果刪兩個,那麽我們是可以通過f[i+1][j-1]轉移而來,如果刪了3個,那麽我們再次枚舉第三個是哪裏,即將問題轉換為了兩個子問題f[i+1][k-1],f[k+1][j-1],區間dp即可求出f數組。
1 #include<cstdio> 2 #include<cstring> 3 #define ll long long 4 #define max(a,b) a>b?a:b 5 using namespace std; 6 const int inf=1e9+1; 7 const int Hash1=1e5+7; 8 const int Hash2=1e5+9; 9 int T,n,m,a[301],dp[301]; 10 bool hs1[100010],hs2[100010]; 11 bool f[301][301]; 12 bool check(int x){ 13 return hs1[((ll)x+inf)%Hash1]&&hs2[((ll)x+inf)%Hash2]; 14 } 15 struct seg{ 16 int l,r; 17 seg(){} 18 seg(int x,int y){ 19 l=x;r=y; 20 } 21 }s[90001]; 22 int cnt; 23 int main() 24 { 25 // freopen("1.txt","r",stdin); 26 scanf("%d",&T); 27 while(T--){ 28 scanf("%d%d",&n,&m); 29 memset(f,0,sizeof(f)); 30 memset(hs1,0,sizeof(hs1)); 31 memset(hs2,0,sizeof(hs2)); 32 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 33 for(int i=1;i<=n;i++) 34 for(int j=1;j<i;j++) 35 f[i][j]=1; 36 for(int i=1;i<=m;i++){ 37 int x; 38 scanf("%d",&x); 39 hs1[(x+inf)%Hash1]=1; 40 hs2[(x+inf)%Hash2]=1; 41 } 42 for(int l=2;l<=n;l++){ 43 for(int i=1;i+l-1<=n;i++){ 44 int j=i+l-1; 45 for(int k=i;k<=j-1;k++){ 46 if(f[i][k]&f[k+1][j])f[i][j]=1; 47 } 48 if(check(a[j]-a[i])&&f[i+1][j-1])f[i][j]=1; 49 for(int k=i+1;k<=j-1;k++){ 50 if(a[k]-a[i]==a[j]-a[k]&&check(a[k]-a[i])){ 51 if(f[i+1][k-1]&&f[k+1][j-1])f[i][j]=1; 52 } 53 } 54 } 55 } 56 cnt=0; 57 for(int i=1;i<n;i++) 58 for(int j=i+1;j<=n;j++) 59 if(f[i][j])s[++cnt]=seg(i,j); 60 memset(dp,0,sizeof(dp)); 61 int now=1; 62 for(int i=1;i<=n;i++){ 63 dp[i]=max(dp[i],dp[i-1]); 64 while(s[now].l==i&&now<=cnt){ 65 dp[s[now].r]=max(dp[s[now].r],dp[i-1]+s[now].r-s[now].l+1); 66 now++; 67 } 68 } 69 printf("%d\n",dp[n]); 70 } 71 return 0; 72 }View Code
hdu5693 D Game