SRM552 Div1Medium FoxAndFlowerShopDivOne
来源:互联网 发布:屏蔽按键软件 编辑:程序博客网 时间:2024/06/08 17:36
【分析】
题目核心的意思就是找两个不相交的矩形并维护矩形中的信息。
然而朴素的暴力枚举当然是过不了的(n≤30)
因为做过求面积这类的问题,所以就想到了扫描线。
而且这个扫描线既要枚举垂直于x轴的,也要枚举垂直于y轴的。
但是单纯的扫描线并不能解决问题。我们要满足区域内百合花的数量与牵牛花的数量之差的绝对值不超过K的情况下再去寻找数量最大的。
我们将百合花定义为1,牵牛花定义为-1。
我们可以用dp[i][j]表示对于x=i这条扫描线左边的花之和为j的花的数量最多。
rdp[i][j]表示右边。
这样就可以转移了。
y=i的情况同理。
注意:既然有-1,那么我们一定要将j加上一个数,防止他爆炸。但是这么做会有很多的小细节。希望大家要慢慢调。
【代码】
#include<cstdio>#include<cstring>#include<cctype>#include<algorithm>#include<iostream>#include<string>#include<vector> using namespace std;#define N 35#define M 2000#define oo 1e9char A[N][N];int ans=-oo,n,m,lim;int B[N][N],C[N][N];int dp[N][M],rdp[N][M];void chk(int &x,int y){ if(x<y)x=y;}int sum(int x1,int y1,int x2,int y2) { return B[x2][y2]+B[x1-1][y1-1]-B[x2][y1-1]-B[x1-1][y2];}int calc(int x1,int y1,int x2,int y2) { return C[x2][y2]+C[x1-1][y1-1]-C[x2][y1-1]-C[x1-1][y2];}int main(){ scanf("%d %d %d",&n,&m,&lim); for(int i=0;i<n;i++)scanf("%s",A[i]); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(A[i-1][j-1]=='L')B[i][j]=1; if(A[i-1][j-1]=='P')B[i][j]=-1; if(B[i][j])C[i][j]=1; B[i][j]+=B[i-1][j]+B[i][j-1]-B[i-1][j-1]; C[i][j]+=C[i-1][j]+C[i][j-1]-C[i-1][j-1]; } } for(int i=0;i<=n+1;i++)for(int j=0;j<=1800;j++)dp[i][j]=rdp[i][j]=-oo; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ for(int x=1;x<=i;x++){ for(int y=1;y<=j;y++){ int t=sum(x,y,i,j)+900; chk(dp[i][t],calc(x,y,i,j)); } } } for(int j=0;j<=1800;j++)chk(dp[i][j],dp[i-1][j]); } for(int i=n;i>=1;i--){ for(int j=1;j<=m;j++){ for(int x=i;x<=n;x++){ for(int y=j;y<=m;y++){ int t=sum(i,j,x,y)+900; chk(rdp[i][t],calc(i,j,x,y)); } } } for(int j=0;j<=1800;j++)chk(rdp[i][j],rdp[i+1][j]); } for(int i=1;i<n;i++){ for(int j=0;j<=1800;j++){ int l=max(0,1800-j-lim); int r=min(1800,1800+lim-j); for(int k=l;k<=r;k++){ if(j+k-1800<-k||j+k-1800>k)continue; chk(ans,dp[i][j]+rdp[i+1][k]); } } } for(int i=0;i<=m+1;i++){ for(int j=0;j<=1800;j++)dp[i][j]=rdp[i][j]=-oo; } for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ for(int x=1;x<=j;x++){ for(int y=1;y<=i;y++){ int t=sum(x,y,j,i)+900; chk(dp[i][t],calc(x,y,j,i)); } } } for(int j=0;j<=1800;j++)chk(dp[i][j],dp[i-1][j]); } for(int i=m;i>=1;i--){ for(int j=1;j<=n;j++){ for(int x=j;x<=n;x++){ for(int y=i;y<=m;y++){ int t=sum(j,i,x,y)+900; chk(rdp[i][t],calc(j,i,x,y)); } } } for(int j=0;j<=1800;j++)chk(rdp[i][j],rdp[i+1][j]); } for(int i=1;i<m;i++){ for(int j=0;j<=1800;j++){ int l=max(0,1800-j-lim); int r=min(1800,1800+lim-j); for(int k=l;k<=r;k++){ if(j+k-1800<-k||j+k-1800>k)continue; chk(ans,dp[i][j]+rdp[i+1][k]); } } } if(ans<0)ans=-1; printf("%d\n",ans); return 0;}
0 0
- SRM552 Div1Medium FoxAndFlowerShopDivOne
- SRM552 Div1Medium FoxAndFlowerShopDivOne
- SRM552
- SRM552 FoxPlusMinus
- SRM 552 - 500 FoxAndFlowerShopDivOne
- Topcoder SRM552 Div1 500
- SRM552题解 (T3除外)
- SRM548 Div1Medium KingdomAndDice
- SRM551 Div1Medium ColorfulWolves
- SRM573 Div1Medium Ski Resorts
- SRM574 Div1Medium PolygonTraversal
- SRM579 Div1Medium TravellingPurchasingMan
- SRM588 Div1Medium KeyDungeonDiv1
- SRM589 Div1Medium GearsDiv1
- SRM554 Div1Medium TheBrickTowerMediumDivOne
- SRM548 Div1Medium KingdomAndDice
- SRM551 Div1Medium ColorfulWolves
- SRM593 Div1Medium MayTheBestPetWin
- Oracle问题总结
- AndroidStudio 中如何查看获取MD5和SHA1值(应用签名)
- CSS常用菜单(四)
- iOS 微信支付流程
- 如何实现点击直接进入编辑状态
- SRM552 Div1Medium FoxAndFlowerShopDivOne
- Android Studio的极速运行gradle编译apk最全攻略
- SQL总结---编辑类
- java.io.IOException: Could not locate executable null\bin\winutils.exe in the Hadoop binaries
- Android实战——Zxing实现二维码扫描
- GDOI2017总结
- <1-1>操作系统的概念
- LeetCode算法题目:Merge k Sorted Lists
- SQL总结---触发器