LOJ 2550 「JSOI2018」机器人——找规律+DP
题目:https://loj.ac/problem/2550
只会写20分的搜索……
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
int n,m,ans;
bool b[N][N],vis[N][N];
void dfs(int x,int y,bool fx,int lj)
{
if(y>m)y=; if(x>n)x=;
if(vis[x][y])
{
if(x==&&y==)
{
bool fg=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(!vis[i][j]){fg=;break;}
if(!fg)ans+=lj;
}
return;
}
if(b[x][y])fx=; if(!fx)lj++;
vis[x][y]=;
dfs(x+,y,fx,lj); dfs(x,y+,fx,lj);
vis[x][y]=;
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%1d",&b[i][j]);
ans=;
dfs(,,,);
printf("%d\n",ans);
}
return ;
}
观察多篇题解:
https://blog.csdn.net/qq_39972971/article/details/80441415
https://www.cnblogs.com/cjyyb/p/10422074.html
https://blog.csdn.net/scar_lyw/article/details/80411617
由结论可知合法的方案取决于左上角 d*d 怎么决策。(副对角线可以拐,所以是 d 条而不是 2*d-1 条)
枚举 d*d 里向下 i 步,向右 j=d-i 步,那么需要 i 和 n 互质、 j 和 m 互质。这样就是合法方案。考虑已知 i , j ,算贡献。
每个位置 ( x, y ) 都会在 “一轮”(d步) 之后走到 ( x+i , y+j ) 。
( 1, 1 ) 位置第一轮走到 ( i+1 , j+1 ) 。考虑 DP 这个第一轮的走法,就知道全局的走法了。
( 1, 1 ) 只能向下走或向右走。走过位置 ( x, y ) ,意味着会在之后的轮中把 ( x+k*i , y+k*j ) 都走过。
把 “走到第一个障碍为止的步数” 改成 “走到每个障碍为止的步数中的最小值” , 一个位置 ( x, y ) 的权值就是所有 ( x+k*i , y+k*j ) 的是障碍的点的 “走到该点的步数最小值” 取 min ;
就是要 DP 一条从 ( 1, 1 ) 到 ( i+1 , j+1 ) 的只能向下或向右走的路径,该路径贡献是路径上各点权值的最小值。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int Mn(int a,int b){return a<b?a:b;}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
const int N=,M=N*N,mod=;
int upt(int x){while(x>=mod)x-=mod;while(x<)x+=mod;return x;} int n,m,lm,c[N][N],dp[N][N][M],ans;
bool b[N][N];
void cz(int &x,int y){x=upt(x+y);}
void solve(int x,int y)
{
memset(dp,,sizeof dp);
dp[][][c[][]]=;
for(int i=;i<=x+;i++)
for(int j=;j<=y+;j++)
for(int k=;k<=lm;k++)
{
int tp=dp[i][j][k]; if(!tp)continue;
if(i<=x)cz(dp[i+][j][Mn(k,c[i+][j])],tp);
if(j<=y)cz(dp[i][j+][Mn(k,c[i][j+])],tp);
}
for(int k=;k<=lm;k++)
ans=(ans+(ll)k*dp[x+][y+][k])%mod;
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
ans=;
scanf("%d%d",&n,&m); lm=n*m;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%1d",&b[i][j]);
int g=gcd(n,m);
for(int x=;x<g;x++)
{
int y=g-x;
if(gcd(x,n)!=||gcd(y,m)!=)continue;
for(int i=;i<=x+;i++)
for(int j=;j<=y+;j++)
{
int d=i+j-;
if(b[i][j]){c[i][j]=d;continue;}
int tx=i+x, ty=j+y; d+=g;
if(tx>n)tx-=n; if(ty>m)ty-=m;
while()
{
if(b[tx][ty]||(tx==i&&ty==j))
{c[i][j]=d;break;}
tx+=x; ty+=y; d+=g;
if(tx>n)tx-=n;if(ty>m)ty-=m;
}
}
solve(x,y);
}
printf("%d\n",ans);
}
return ;
}
LOJ 2550 「JSOI2018」机器人——找规律+DP的更多相关文章
- 【LOJ】#2550. 「JSOI2018」机器人
题解 我不会打表找规律啊QAQ 规律就是 对于\(n = m\)我们每一条左下到右上的对角线上的点的走法都是一样的且每n步一个轮重复 对于\(n != m\)我们找到最大公约数\(d\),在每个\(d ...
- LOJ 2546 「JSOI2018」潜入行动——树形DP
题目:https://loj.ac/problem/2546 dp[ i ][ j ][ 0/1 ][ 0/1 ] 表示 i 子树,用 j 个点,是否用 i , i 是否被覆盖. 注意 s1<= ...
- LOJ 2548 「JSOI2018」绝地反击 ——二分图匹配+网络流手动退流
题目:https://loj.ac/problem/2548 如果知道正多边形的顶点,就是二分答案.二分图匹配.于是写了个暴力枚举多边形顶点的,还很愚蠢地把第一个顶点枚举到 2*pi ,其实只要 \( ...
- LOJ 2551 「JSOI2018」列队——主席树+二分
题目:https://loj.ac/problem/2551 答案是排序后依次走到 K ~ K+r-l . 想维护一个区间排序后的结果,使得可以在上面二分.求和:二分可以知道贡献是正还是负. 于是想用 ...
- LOJ 2547 「JSOI2018」防御网络——思路+环DP
题目:https://loj.ac/problem/2547 一条树边 cr->v 会被计算 ( n-siz[v] ) * siz[v] 次.一条环边会被计算几次呢?于是去写了斯坦纳树. #in ...
- @loj - 3157@「NOI2019」机器人
目录 @description@ @solution@ @accepted code@ @details@ @description@ 小 R 喜欢研究机器人. 最近,小 R 新研制出了两种机器人,分 ...
- 「JSOI2018」机器人
在本题当中为了方便,我们将坐标范围改至 \((0 \sim n - 1, 0 \sim m - 1)\),行走即可视作任意一维在模意义下 \(+1\). 同时,注意到一个位置只能经过一次,则可以令 \ ...
- LOJ 3092 「BJOI2019」排兵布阵 ——DP
题目:https://loj.ac/problem/3092 同一个人的不同城堡之间没有什么联系,只是和<=m.所以对每个城堡的 s 个值排序,做一个 f[ i ][ j ] 表示第 i 个城堡 ...
- Loj #3059. 「HNOI2019」序列
Loj #3059. 「HNOI2019」序列 给定一个长度为 \(n\) 的序列 \(A_1, \ldots , A_n\),以及 \(m\) 个操作,每个操作将一个 \(A_i\) 修改为 \(k ...
随机推荐
- ubuntu的安装与vim(部分)文件的配置
Ubuntu的安装与vim相关的配置 虚拟机环境的安装(先说说虚拟机的安装步骤把) 对于安装ubuntu来讲不是很难掌握,但是在Linux系统虚拟机下提供了很多便利的手段,而要配置一个顺手的虚拟机环境 ...
- Debian 系linux切换登录管理器(display manager)
在控制台中sudo dpkg-reconfigure <你的dm包名>即可dm选择列表,选择自己需要的dm 例如ubutu18默认使用gdm3,则输入命令: sudo dpkg-recon ...
- 关于redis的安装
下载redis 我这边下载redis4.0.1版本, 然后解压 然后执行yum -y install gcc gcc-c++ libstdc++-devel 然后cd //qbtapp/redis-4 ...
- 文件传输协议(FTP)
文件传输协议(FTP)用于用户在两台主机之间进行远距离的文件传输,并保证传输的可靠性. FTP采用客户机/服务器的方式,由FTP服务器和FTP客户机两部分组成. FTP服务器中以目录结构保存着各种文件 ...
- python练习:实现一个整数数组里面两个数之和为183的所有整数对
l1 = [183,0,1,2,-184,367] num = [] for i in range (0,len(l1)): for l in range (i+1,len(l1)): if l1[i ...
- 【转】反编译D-Link路由器固件程序并发现后门
固件是D-link无线路由器(型号:DIR-100 revA)的固件程序 v1.13.使用工具Binwalk,很快的就从中发现并提取出一个只读SquashFS文件系统,没用多大功夫我就将这个固件程序的 ...
- TabLayout下划线指示器自适应文字宽度
解决方案1: 更新design库到28.0.0-rc01 implementation 'com.android.support:design:28.0.0-rc01' 然后在TabLayout里设置 ...
- 浅谈java中的String、StringBuffer、StringBuilder类的区别以及关系
在java中最常见的使用就是对字符串的操作:首先先说一下对字符串的理解:字符串就是一连串字符序列,Java提供了String和StringBuffer两个类来封装字符串,并提供一系列方法来操作字符串对 ...
- adb环境配置+常用adb命令+Logcat命令的用法+手动进行文件比对的方法+批量挪bug
1. adb环境配置:下载adb环境变量包:打开计算机属性-高级系统设置-环境变量:新建变量adb,值为刚才的环境变量包路径:编辑path值,在最后面加上;%adb%;确定就妥了 2. 常用adb命令 ...
- git 恢复本地误删文件
git status git reset HEAD 路径(git status 会显示的路径) git checkout 路径