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 }

 

posted @ 2017-10-25 23:03  WeiAR  阅读(272)  评论(0编辑  收藏  举报