题目大概说给一张地图,地图每个格子都有0到9中的某一个数字。现在要在一个格子放炸弹,炸弹爆炸后水柱有两种扩展方式,一种是上、下、左、右,另一种是左上、右下、右上、左下,且四个方向的长度都一样。问放哪个格子怎么爆炸使得水柱覆盖的格子上的数字乘积最大,结果模1e9+7。

这题不会做。。

  • 首先,各个格子的值取对数,这个为了比大小,因为需要模数,通过取对数缩小值。另外也把乘法转化成加法。这是个挺经典的技巧。
  • 接下来,水柱的话肯定不能延长到0,不然功亏一篑,那么利用DP求出各个格子向8各个方向能延长多长,即dp[dir][x][y]。转移就是格子(x,y)不为0,从dp[dir][x+d[dir]][y+d[dir]]+1这儿转移,否则值为0。具体我是用记忆话搜索实现的。
  • 然后知道各个格子8个方向能延长最长长度,上、下、左、右四个方向能够延长的最小值就是第一种水柱的拓展最优的长度,而左上、右下、右上、左下四个方向的最小值就是第二种了。
  • 如何快速得出各个方向水柱覆盖的数字和——利用前缀和!这也是个挺经典的技巧。而取对数把乘法转化成加法,这就使得能利用前缀和的差求区间和。那么预处理出各个方向的前缀和就能在O(1)得出区间和了,即水柱覆盖到的格子的和。
  • 最后就是通过枚举每个格子,得到各个格子放炸弹最多能得到的数字和,更新答案。

注意最后的答案不要直接求次幂还原。。会有精度问题。。应该要记录下来,在原地图中把各个数字累乘出答案。。

 #include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std; int n;
double a[][];
int b[][];
//上、下、右、左、左上、右下、右上、左下
int dx[]={-,,,,-,,-,};
int dy[]={,,,-,-,,,-}; int d[][][];
int dp(int dir,int x,int y){
if(a[x][y]<) return d[dir][x][y]=;
if(d[dir][x][y]!=-) return d[dir][x][y];
int nx=x+dx[dir],ny=y+dy[dir],res=;
if(nx>= && nx<=n && ny>= && ny<=n) res+=dp(dir,nx,ny);
return d[dir][x][y]=res;
} double sum[][][];
int rec1[][],rec2[][]; int main(){
scanf("%d",&n);
for(int i=; i<=n; ++i){
for(int j=; j<=n; ++j){
scanf("%1d",&b[i][j]);
if(b[i][j]==) a[i][j]=-;
else a[i][j]=log2(b[i][j]);
}
}
for(int i=; i<=n; ++i){
for(int j=; j<=n; ++j){
sum[][i][j]=sum[][i][j-]+a[j][i];
}
}
for(int i=; i<=n; ++i){
for(int j=; j<=n; ++j){
sum[][i][j]=sum[][i][j-]+a[i][j];
}
}
for(int i=n; i>=; --i){
int x=i,y=;
for(int j=; j<=n-i+; ++j){
sum[][n-i+][j]=sum[][n-i+][j-]+a[x][y];
rec1[x][y]=j;
++x; ++y;
}
}
for(int i=; i<=n; ++i){
int x=,y=i;
for(int j=; j<=n-i+; ++j){
sum[][n+i-][j]=sum[][n+i-][j-]+a[x][y];
rec1[x][y]=j;
++x; ++y;
}
}
for(int i=; i<=n; ++i){
int x=,y=i;
for(int j=; j<=i; ++j){
sum[][i][j]=sum[][i][j-]+a[x][y];
rec2[x][y]=j;
++x; --y;
}
}
for(int i=; i<=n; ++i){
int x=i,y=n;
for(int j=; j<=n-i+; ++j){
sum[][n+i-][j]=sum[][n+i-][j-]+a[x][y];
rec2[x][y]=j;
++x; --y;
}
}
memset(d,-,sizeof(d));
for(int k=; k<; ++k){
for(int i=; i<=n; ++i){
for(int j=; j<=n; ++j){
dp(k,i,j);
}
}
}
double ans=-;
int ansx,ansy,ansdir=-,anslen;
for(int i=; i<=n; ++i){
for(int j=; j<=n; ++j){
if(a[i][j]<) continue; int len=min(min(d[][i][j],d[][i][j]),min(d[][i][j],d[][i][j]));
double res=;
res+=sum[][j][i]-sum[][j][i-len];
res+=sum[][j][i+len-]-sum[][j][i];
res+=sum[][i][j-]-sum[][i][j-len];
res+=sum[][i][j+len-]-sum[][i][j];
if(ans<res){
ans=res;
ansx=i; ansy=j; ansdir=; anslen=len;
} len=min(min(d[][i][j],d[][i][j]),min(d[][i][j],d[][i][j]));
res=;
res+=sum[][n-i+j][rec1[i][j]]-sum[][n-i+j][rec1[i][j]-len];
res+=sum[][n-i+j][rec1[i][j]+len-]-sum[][n-i+j][rec1[i][j]];
res+=sum[][i+j-][rec2[i][j]-]-sum[][i+j-][rec2[i][j]-len];
res+=sum[][i+j-][rec2[i][j]+len-]-sum[][i+j-][rec2[i][j]];
if(ans<res){
ans=res;
ansx=i; ansy=j; ansdir=; anslen=len;
}
}
}
if(ansdir==-){
printf("");
return ;
}
long long res=;
if(ansdir==){
for(int i=ansx-anslen+; i<=ansx+anslen-; ++i){
res*=b[i][ansy];
res%=;
}
for(int i=ansy-anslen+; i<=ansy+anslen-; ++i){
if(i==ansy) continue;
res*=b[ansx][i];
res%=;
}
}else{
int x=ansx-anslen+,y=ansy-anslen+;
for(int i=; i<anslen*; ++i){
res*=b[x][y];
res%=;
++x; ++y;
}
x=ansx-anslen+; y=ansy+anslen-;
for(int i=; i<anslen*; ++i){
if(x==ansx && y==ansy){
++x; --y;
continue;
}
res*=b[x][y];
res%=;
++x; --y;
}
}
printf("%lld",res);
return ;
}

Codeforces 677E Vanya and Balloons(DP + 一些技巧)的更多相关文章

  1. Codeforces 677E Vanya and Balloons

    Vanya and Balloons 枚举中心去更新答案, 数字过大用log去比较, 斜着的旋转一下坐标, 然后我旋出来好多bug.... #include<bits/stdc++.h> ...

  2. Codeforces 677D - Vanya and Treasure - [DP+优先队列BFS]

    题目链接:http://codeforces.com/problemset/problem/677/D 题意: 有 $n \times m$ 的网格,每个网格上有一个棋子,棋子种类为 $t[i][j] ...

  3. Codeforces 677D Vanya and Treasure 暴力+BFS

    链接 Codeforces 677D Vanya and Treasure 题意 n*m中有p个type,经过了任意一个 type=i 的各自才能打开 type=i+1 的钥匙,最初有type=1的钥 ...

  4. codeforces 492E. Vanya and Field(exgcd求逆元)

    题目链接:codeforces 492e vanya and field 留个扩展gcd求逆元的板子. 设i,j为每颗苹果树的位置,因为gcd(n,dx) = 1,gcd(n,dy) = 1,所以当走 ...

  5. [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆)

    [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆) 题面 一棵二叉树的所有点的点权都是给定的集合中的一个数. 让你求出1到m中所有权 ...

  6. Codeforces Round #355 (Div. 2) D. Vanya and Treasure dp+分块

    题目链接: http://codeforces.com/contest/677/problem/D 题意: 让你求最短的从start->...->1->...->2->. ...

  7. Codeforces 900 E. Maximum Questions (DP,技巧)

    题目链接:900 E. Maximum Questions 题意: 给出一个长度为n只含有a和b还有'?'的串s,且'?'可以被任意替换为a或b.再给出一个字符串t (奇数位上为a,偶数位上为b,所以 ...

  8. E. Vanya and Balloons Codeforces Round #355 (Div. 2)

    http://codeforces.com/contest/677/problem/E 题意:有n*n矩形,每个格子有一个值(0.1.2.3),你可以在矩形里画一个十字(‘+’形或‘x’形),十字的四 ...

  9. codeforces 721C (拓排 + DP)

    题目链接:http://codeforces.com/contest/721/problem/C 题意:从1走到n,问在时间T内最多经过多少个点,按路径顺序输出. 思路:比赛的时候只想到拓排然后就不知 ...

随机推荐

  1. [Android Pro] root用户删除文件提示:Operation not permitted

    reference to : http://blog.csdn.net/evanbai/article/details/6187578 一些文件看上去可能一切正常,但当您尝试删除的时候,居然也会报错, ...

  2. 关于 UICollectionViewCell 的一些陷阱

    如果直接使用 UICollectionViewCell 的自带属性 selected 来自定义一些样式,如: - (void)setSelected:(BOOL)selected { [super s ...

  3. windows一个目录下最大文件数目

    对于FAT16文件系统, 可以保存的文件体积最大值是 4 GB - 1 byte (2^32 bytes - 1 byte): 卷的最大体积是4GB:每个卷上最多可以保存的文件数量是65,536个 ( ...

  4. EF增删改查基础

    #region 1.0 新增 -void Add() /// <summary> /// 1.0 新增 /// </summary> static void Add() { / ...

  5. android SDK 更新问题完美解决 http://dl-ssl.google.com refused

    现在由于GWF,google基本和咱们说咱见了,就给现在在做Android  或者想学习Android 的朋友带来了诸多的不便,最简单的就是Android SDK Manager 你无法更新了. 现在 ...

  6. Quartus II9.0 使用中文输入的方法

      Quartus II可以用中文了 我们都知道高版本的quartus里面不支持中文,就连最新版的10.0也不支持,还好找到了一种方法,和大家分享一下: 具体步骤:quartus ——tools——o ...

  7. 【数据库】 Sqlserver 2008 error 40出现连接错误的解决方法

    经常要连接到远程数据库上,因此常常碰到这个错误,然后又屡次忘记解决方法,所以今天坐下笔迹,好下次能快速回忆起来. 一.首先检查数据库的TCP/TP是否启动 1.启动Sql server配置管理器 2. ...

  8. .net学习之泛型、程序集和反射

    一.泛型1.CLR编译时,编译器只为MyList<T>类型产生“泛型版”的IL代码——并不进行泛型的实例化,T在中间只充当占位符.例如:MyList 类型元数据中显示的<T> ...

  9. ViewPager onPageChangeListener总结(转)

    android ViewPager滑动事件讲解 今天在做项目的时候,由于要处理viewPager页面滑动的事件,所以对其进行了一个小小的研究: 首先ViewPager在处理滑动事件的时候要用到OnPa ...

  10. Android在listview添加checkbox实现单选多选操作问题(转)

    转自:http://yangshen998.iteye.com/blog/1310183 在Android某些开发需求当中,有时候需要在listveiw中加入checkbox实现单选,多选操作.表面上 ...