rt,求给定格子数的凸连通块最大价值。
其实刚看到凸连通块的时候有点懵逼,因为不知道这是啥,网上也没定义。瞟了一眼lyd题解第一行,说是左端先(非严格)递减,再(非严格)递增,右端先(非严格)递增,再(非严格)递减的就是凸连通块。
那就只看左右端的单调性变化情况。。考虑到每行选的连续格子和上一行有联系,用DP转移。
$f[i][k][l][0/1][r][0/1]$表示到第$i$行,选了$k$个格子,选的左端点是$l$,和上一行的关系是单调减或增(0 or 1),右端点是$r$,单调性同左的状态下最大价值。【因为要考虑单调性的变化情况,故需要设计01状态】
然后就是枚举行,左右端点,上一行的左右端点,以及选格子数,根据单调情况来无脑转移。
分五种情况大力讨论即可。
- 从这一行才开始选
- 左侧增,右侧增
- 左侧增,右侧减
- 左侧减,右侧增
- 左侧减,右侧减
然后每种情况具体画线段图就可以知道从上一行的什么单调情况转移了,不放latex了,直接看code。
理论复杂度$O(N^7)$,$N leqslant 15$,按说1000ms是过不了的,不过。。枚举过程常数大概在$frac{1}{8}$~$frac{1}{4}$左右,再带点前缀和、区间长度预处理什么的卡卡也就能过去了。
WA:
因为码力不行,对于这种大力讨论的题,真心不容易一遍敲对。line45~48转移的时候忘了加sum。。不过也是很显眼的错误呢,毕竟WA答案逼近正解时基本是初始化和转移的个别一两句话写错,这时候应将肉眼调试范围放至转移的部分。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 #define dbg(x) cerr<<#x<<" = "<<x<<endl 8 #define ddbg(x,y) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<endl 9 #define rep(i,a,b) for(register int i=a;i<=b;++i) 10 using namespace std; 11 typedef long long ll; 12 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;} 13 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;} 14 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 15 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 16 template<typename T>inline T read(T&x){ 17 x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; 18 while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; 19 } 20 const int N=17; 21 struct thxorz{ 22 int l,r,dl,dr; 23 thxorz(int l=0,int r=0,int dl=0,int dr=0):l(l),r(r),dl(dl),dr(dr){} 24 }g[N][N*N][N][2][N][2]; 25 int f[N][N*N][N][2][N][2],len[N][N],val[N][N][N],mp[N][N]; 26 int n,m,K,sum,ans; 27 28 int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout); 29 read(n),read(m),read(K); 30 rep(i,1,n){ 31 rep(j,1,m)read(mp[i][j]),val[0][0][j]=val[0][0][j-1]+mp[i][j]; 32 rep(j,1,m)rep(l,1,j)val[i][l][j]=val[0][0][j]-val[0][0][l-1]; 33 } 34 memset(val[0][0],0,sizeof val[0][0]); 35 rep(i,1,m)rep(j,i,m)len[i][j]=j-i+1; 36 rep(i,1,m)rep(j,i,m)f[1][len[i][j]][i][0][j][0]=f[1][len[i][j]][i][0][j][1]=f[1][len[i][j]][i][1][j][0]=f[1][len[i][j]][i][1][j][1]=val[1][i][j]; 37 rep(i,2,n)rep(l,1,m)rep(r,l,m){ 38 sum=val[i][l][r]; 39 f[i][len[l][r]][l][0][r][0]=f[i][len[l][r]][l][1][r][0]=f[i][len[l][r]][l][0][r][1]=f[i][len[l][r]][l][1][r][1]=val[i][l][r]; 40 rep(L,1,l)rep(R,l,r)rep(k,len[l][r]+len[L][R],len[l][r]+len[L][R]+(i-2)*m){ 41 if(MAX(f[i][k][l][1][r][1],f[i-1][k-len[l][r]][L][0][R][1]+sum))g[i][k][l][1][r][1]=thxorz(L,R,0,1); 42 if(MAX(f[i][k][l][1][r][1],f[i-1][k-len[l][r]][L][1][R][1]+sum))g[i][k][l][1][r][1]=thxorz(L,R,1,1); 43 } 44 rep(L,1,l)rep(R,r,m)rep(k,len[l][r]+len[L][R],len[l][r]+len[L][R]+(i-2)*m){ 45 if(MAX(f[i][k][l][1][r][0],f[i-1][k-len[l][r]][L][0][R][0]+sum))g[i][k][l][1][r][0]=thxorz(L,R,0,0); 46 if(MAX(f[i][k][l][1][r][0],f[i-1][k-len[l][r]][L][0][R][1]+sum))g[i][k][l][1][r][0]=thxorz(L,R,0,1); 47 if(MAX(f[i][k][l][1][r][0],f[i-1][k-len[l][r]][L][1][R][0]+sum))g[i][k][l][1][r][0]=thxorz(L,R,1,0); 48 if(MAX(f[i][k][l][1][r][0],f[i-1][k-len[l][r]][L][1][R][1]+sum))g[i][k][l][1][r][0]=thxorz(L,R,1,1); 49 } 50 rep(L,l,r)rep(R,L,r)rep(k,len[l][r]+len[L][R],len[l][r]+len[L][R]+(i-2)*m){ 51 if(MAX(f[i][k][l][0][r][1],f[i-1][k-len[l][r]][L][0][R][1]+sum))g[i][k][l][0][r][1]=thxorz(L,R,0,1); 52 } 53 rep(L,l,r)rep(R,r,m)rep(k,len[l][r]+len[L][R],len[l][r]+len[L][R]+(i-2)*m){ 54 if(MAX(f[i][k][l][0][r][0],f[i-1][k-len[l][r]][L][0][R][0]+sum))g[i][k][l][0][r][0]=thxorz(L,R,0,0); 55 if(MAX(f[i][k][l][0][r][0],f[i-1][k-len[l][r]][L][0][R][1]+sum))g[i][k][l][0][r][0]=thxorz(L,R,0,1); 56 } 57 } 58 thxorz orz;int k=K,row; 59 rep(i,(K-1)/m+1,n)rep(l,1,m)rep(r,l,m){ 60 if(MAX(ans,f[i][K][l][0][r][0]))orz=thxorz(l,r,0,0),row=i; 61 if(MAX(ans,f[i][K][l][0][r][1]))orz=thxorz(l,r,0,1),row=i; 62 if(MAX(ans,f[i][K][l][1][r][0]))orz=thxorz(l,r,1,0),row=i; 63 if(MAX(ans,f[i][K][l][1][r][1]))orz=thxorz(l,r,1,1),row=i; 64 } 65 while(k){ 66 rep(i,orz.l,orz.r)mp[row][i]=-1;k-=len[orz.l][orz.r]; 67 orz=g[row--][k+len[orz.l][orz.r]][orz.l][orz.dl][orz.r][orz.dr]; 68 } 69 printf("Oil : %d ",ans); 70 rep(i,1,n)rep(j,1,m)if(mp[i][j]==-1)printf("%d %d ",i,j); 71 return 0; 72 }