Problem B. Mural Google Kickstart Round H 2018
題意:畫家在牆上畫壁畫,牆在水平方向被分成N段,每一段有一個value值。畫家每天畫一段而且只能在已經畫過的sections邊上接著畫。每天會來一次洪水,洪水會毀掉未被畫過的,且之和一個section相連的部分。被洪水會掉的部分不能在畫畫。問在worst case下,畫家能得到的最大value是多少。
這一題題目很繞,洪水每次只能毀掉剩餘的section中最左邊or最右邊沒被畫過的部分。畫家畫的壁畫也是連續的。看到worst case還以為是博弈,但是博弈我只會dp,但博弈dp裡面先手後手的行為要是相同的。然而開始沒看懂題目要求worst case,發現test case裡面的結果是長度為N/2 or N/2+1的子序列最大和。
後來想想,因為畫家的action更加active,所以可以保證其畫到的是和最大的子序列。如果flood已經到達了max susequence邊上,畫家可以先將那個邊界畫上。
比如: 1 0 2 9 3 8 4 7 5 6,最大子序列是 9 3 8 4 7
最佳策略是從8開始畫。如果洪水的順序是先左邊後右邊,策略是:paint 8, destroy 1, parint 3, destroy 0, paint 9 destroy 2, paint 4 destroy 6, paint 7, destroy 5
如果洪水的順序是左右交替,策略是:paint 8, destroy 1, parint 4, destroy 6, paint 3 destroy 0, paint 7 destroy 5, paint 9, destroy 2
如果洪水的順序是右左交替,策略是:paint 8, destroy 6, parint 4, destroy 1, paint 3 destroy 5, paint 7 destroy 0, paint 9, destroy 2
感覺最佳策略是從中心開始畫,因為這樣可以向左向右都expand。如果洪水毀了左邊,在center的左邊畫一個section,如果洪水毀了右邊,就在center右邊畫一個section。
#include<iostream> #include<stdio.h> #include<cstdio> #include<string> #include<cmath> #include<stdlib.h> #include<algorithm> #include<string.h> #include<cstring> #include<vector> #include<queue> #include<map> #include<set> #include<ctime> using namespace std; //Kickstart Round H Problem B const int maxn=5*1e6+10; int T; int N; int arr[maxn]; int ans; int main() { int x=maxn*9; cout<<x<<endl; return 0; // freopen("input.txt","r",stdin); freopen("B-large.in","r",stdin); freopen("B-large.txt","w",stdout); clock_t START_TIME; clock_t FINISH_TIME; START_TIME=clock(); scanf("%d",&T); for(int ca=1;ca<=T;ca++) { memset(arr,0,sizeof(arr)); ans=0; cin>>N; string tmp; cin>>tmp; cin.ignore(); for(int i=0;i<N;i++) { arr[i]=tmp[i]-'0'; } int len=0; if(N%2==0) { len=N/2; } else { len=N/2+1; } int windowsum=0; for(int i=0;i<len-1;i++) { windowsum+=arr[i]; } for(int i=0;i+len<=N;i++) { windowsum+=arr[i+len-1]; ans=max(ans,windowsum); windowsum-=arr[i]; } printf("Case #%d: %d\n",ca,ans); cerr<<"finish case "<<ca<<endl; } FINISH_TIME=clock(); cerr<<1.0*(FINISH_TIME-START_TIME)/CLOCKS_PER_SEC <<" (s) "<<endl; return 0; }