这题做出来了很有成就感(骄傲.jpg)
虽然这题没评级,但我感觉应该有紫题难度吧?
Solution:
数据很小,然后题目里说了要横纵分解区域。
所以可以从这里出发,dfs分解区域。
具体怎么分解:可以发现,如果在这个地方分解开当前区域,那么必须满足两边断电后都能满足。
如果可以,那么再去看是否能分解到更小的即可。
做到这里之后,一交,T了。
显然,过于暴力了。
考虑记忆化搜素,设dp[x1][y1][x2][y2]表示区域(x1,y1)~(x2,y2)能分解成的最多区域数。
交了一发又T了,原来一开始我统计区域面积的时候是暴力求的。。显然可以前缀和O(1)求出。
嗯。AC。
注意:题目求的是最大的区域最小值。这里一定要判断清楚。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 1e4+5; const int M = 2e4+5; const LL Mod = 1e9+7; #define rg register #define pi acos(-1) #define INF 1e9 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } void print(int x){ if(x < 0){x = -x;putchar('-');} if(x > 9) print(x/10); putchar(x%10+'0'); } } using namespace FASTIO; void FRE(){/*freopen("data1.in","r",stdin); freopen("data1.out","w",stdout);*/} int n,m,u,a[35][35],sum = 0,pre[35][35]; pii dp[35][35][35][35]; int cal(int x1,int y1,int x2,int y2) { return pre[x2][y2]+pre[x1-1][y1-1]-pre[x1-1][y2]-pre[x2][y1-1]; } pii dfs(int x1,int y1,int x2,int y2,int all) { if(dp[x1][y1][x2][y2].first != 0) return dp[x1][y1][x2][y2]; if(x1 == x2 && y1 == y2) return pii{1,u-(sum-all)}; pii tmp; tmp.first = 1; tmp.second = u-(sum-all); for(int i = y1;i < y2;++i)//纵向划分 { int cal1 = cal(x1,y1,x2,i); int cal2 = cal(x1,i+1,x2,y2); if(sum-cal1 <= u && sum-cal2 <= u) { pii ma1 = dfs(x1,y1,x2,i,cal1); pii ma2 = dfs(x1,i+1,x2,y2,cal2); if(ma1.first+ma2.first > tmp.first) { tmp.first = ma1.first+ma2.first; tmp.second = min(ma1.second,ma2.second); } else if(ma1.first+ma2.first == tmp.first) tmp.second = max(tmp.second,min(ma1.second,ma2.second)); } } for(int i = x1;i < x2;++i)//横向划分 { int cal1 = cal(x1,y1,i,y2); int cal2 = cal(i+1,y1,x2,y2); if(sum-cal1 <= u && sum-cal2 <= u) { pii ma1 = dfs(x1,y1,i,y2,cal1); pii ma2 = dfs(i+1,y1,x2,y2,cal2); if(ma1.first+ma2.first > tmp.first) { tmp.first = ma1.first+ma2.first; tmp.second = min(ma1.second,ma2.second); } else if(ma1.first+ma2.first == tmp.first) tmp.second = max(tmp.second,min(ma1.second,ma2.second)); } } return dp[x1][y1][x2][y2] = tmp; } int main() { n = read(),m = read(),u = read(); for(int i = 1;i <= n;++i) for(int j = 1;j <= m;++j) a[i][j] = read(),sum += a[i][j]; for(int i = 1;i <= n;++i) for(int j = 1;j <= m;++j) pre[i][j] = pre[i][j-1]+pre[i-1][j]-pre[i-1][j-1]+a[i][j]; pii ans = dfs(1,1,n,m,sum);//左下,右上 printf("%d %d ",ans.first,ans.second); // system("pause"); }