P3147 [USACO16OPEN]262144
P3147 [USACO16OPEN]262144
一道非常有趣的游戏,不,题目。
当数据水时,可以这样表示状态。
f[i][j]表示合并[i,j]区间所能得到的最大值,有点floyed的小味道。
if(f[i][k]==f[k+1][j])
f[i][j]=max(f[i][k]+1,f[i][j]);
不断更新答案。
这样需要枚举左右端点和中间点,O(n^3)
300以内的数据可以水过。
状态的设定直接把dp拉到暴力里去了。
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<algorithm> 5 #include<cmath> 6 #include<ctime> 7 #include<cstring> 8 #define inf 2147483647 9 #define For(i,a,b) for(register int i=a;i<=b;i++) 10 #define p(a) putchar(a) 11 #define g() getchar() 12 //by war 13 //2017.10.26 14 using namespace std; 15 int n; 16 int x; 17 int f[300][300]; 18 int ans; 19 void in(int &x) 20 { 21 int y=1; 22 char c=g();x=0; 23 while(c<'0'||c>'9') 24 { 25 if(c=='-') 26 y=-1; 27 c=g(); 28 } 29 while(c<='9'&&c>='0')x=x*10+c-'0',c=g(); 30 x*=y; 31 } 32 void o(int x) 33 { 34 if(x<0) 35 { 36 p('-'); 37 x=-x; 38 } 39 if(x>9)o(x/10); 40 p(x%10+'0'); 41 } 42 int main() 43 { 44 in(n); 45 For(i,1,n) 46 { 47 in(x); 48 f[i][i]=x; 49 } 50 For(j,1,n) 51 for(int i=j;i>=1;i--) 52 For(k,i,j-1) 53 if(f[i][k]==f[k+1][j]) 54 { 55 f[i][j]=max(f[i][k]+1,f[i][j]); 56 ans=max(ans,f[i][j]); 57 } 58 o(ans); 59 return 0; 60 }
O.O
优化状态:
有点倍增的小味道。
i表示数值,j表示区间的左端点,f[i][j]表示右端点,如果存在这样的右端点,就把ans更新为i。怎么转移呢?
if(!f[i][j]&&f[i-1][j])
f[i][j]=f[i-1][f[i-1][j]+1];
画个图就明白了。
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<algorithm> 5 #include<cmath> 6 #include<ctime> 7 #include<cstring> 8 #define inf 2147483647 9 #define For(i,a,b) for(register int i=a;i<=b;i++) 10 #define p(a) putchar(a) 11 #define g() getchar() 12 //by war 13 //2017.10.26 14 using namespace std; 15 int n; 16 int x; 17 int f[65][300];//18M 18 int ans; 19 void in(int &x) 20 { 21 int y=1; 22 char c=g();x=0; 23 while(c<'0'||c>'9') 24 { 25 if(c=='-') 26 y=-1; 27 c=g(); 28 } 29 while(c<='9'&&c>='0')x=x*10+c-'0',c=g(); 30 x*=y; 31 } 32 void o(int x) 33 { 34 if(x<0) 35 { 36 p('-'); 37 x=-x; 38 } 39 if(x>9)o(x/10); 40 p(x%10+'0'); 41 } 42 int main() 43 { 44 in(n); 45 For(i,1,n) 46 { 47 in(x); 48 f[x][i]=i; 49 } 50 For(i,1,60) 51 For(j,1,n) 52 if(!f[i][j]&&f[i-1][j]&&f[i-1][f[i-1][j]+1]) 53 { 54 f[i][j]=f[i-1][f[i-1][j]+1]; 55 ans=i; 56 } 57 o(ans); 58 return 0; 59 }