打了一场luogu的信心赛,惊讶地发现我不会T2,感觉像这样在矩阵里面的dp看起来很套路的样子,但是仔细想想还是有很多需要注意的细节。

又想到之前貌似也考过一些类似的题目 然而我并没有改 ,于是打算补补锅。

目前大概想到几道题,慢慢写吧。

luogu P1006 传纸条 && 小集训模拟赛5 方格取数

很简单的两道题。注意到在“方格取数”中,因为每个方格的数字只能取一次,因此一定不会走重复路线(当然是在所有数字都大于0的情况下)。那就和“传纸条”是同一道题了。

数组可以开4维,3维,貌似还有二维?因为数据范围太小就懒得写优化了。(数据范围大的话貌似就要用网络流了,本Orzer不会)

代码:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
int a[25][25],vis[25][25],dp[25][25][25][25];
void Solve(){
int n;scanf("%d",&n);
int o,u,r;
while(1){
scanf("%d%d%d",&o,&u,&r);
if(!o&&!u&&!r) break;
a[o][u]=r;
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
for(int k=1;k<=n;++k){
for(int x=1;x<=n;++x){
if((i+j)!=(k+x)) continue;
dp[i][j][k][x]=max(max(dp[i-1][j][k-1][x],dp[i][j-1][k-1][x]),max(dp[i-1][j][k][x-1],dp[i][j-1][k][x-1]));
if(i==k) dp[i][j][k][x]+=a[i][j];
else dp[i][j][k][x]=dp[i][j][k][x]+a[i][j]+a[k][x];
}
}
}
}
printf("%d",dp[n][n][n][n]);
}
int main(){
Solve();
return 0;
}

小集训模拟赛12 T2 小象与老鼠

比上面的方格取数稍微难一点。因为每个点对答案造成的贡献不仅仅是这个格子的数,还有四连通的格子。dp时候要考虑去重的问题。

具体是要记录每一个dp值是从它的上面或左面转移过来。这样分类讨论就可以去重。

代码:

代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1000+10;
int a[maxn][maxn];
int val[maxn][maxn],dp[maxn][maxn][2];
int n,m;
void Solve(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
scanf("%d",&a[i][j]);
}
}
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
val[i][j]=a[i+1][j]+a[i][j+1];
}
}
dp[1][1][0]=dp[1][1][1]=val[1][1]+a[1][1];
for(int i=1;i<=n;++i){//0上,1左;
for(int j=1;j<=m;++j){
if(i==1&&j==1) continue;
else if(i==1) dp[i][j][1]=dp[i][j-1][1]+val[i][j];
else if(j==1) dp[i][j][0]=dp[i-1][j][0]+val[i][j];
else{
if(i-1==1) dp[i][j][0]=dp[i-1][j][1]+val[i][j];
else dp[i][j][0]=min(dp[i-1][j][0]+val[i][j]+a[i][j-1],dp[i-1][j][1]+val[i][j]);
if(j-1==1) dp[i][j][1]=dp[i][j-1][0]+val[i][j];
else dp[i][j][1]=min(dp[i][j-1][1]+val[i][j]+a[i-1][j],dp[i][j-1][0]+val[i][j]);
}
}
}
printf("%d",min(dp[n][m][1],dp[n][m][0]));
}
int main(){
Solve();
return 0;
}

luogu P6855 「EZEC-4.5」走方格(2020.10.4 君のNOIP のCSP信心赛 T2)

刚刚做的新题。刚开始的时候觉得很套路,几分钟就把代码写出来了。调了十分钟后过不了样例之后才发现自己错了。

出题人的题解

看了题解才明白。。。我太菜了

首先显然有\(O(n^4)\) 做法。枚举所有点,尝试将其变成0即可。

然后显然可以优化到O(n^3)因为发现如果变成0的点不再原来的最长路上,那么对最终答案是没有贡献的。因此只需要枚举最长路上的点即可。

然后考虑优化。

对于最长路上的某个点,如果把它变成0。

第一种情况,如果把它变成0,它依然在最长路上。

第二种情况,其他的格子会变成最长路上的点。

那应该怎么计算呢?

可以发现,如果把一个点变成0,不影响(1,1)到这个点之前的所有点的最长路。

同时还可以发现,如果反过来想,如果把一个点变成0,也不影响这个点之后的所有点到(n,m)的最长路。

于是我们可以预处理出两个数组:

dp[i][j]表示(1,1)到(i,j)的最长路,f[i][j]表示(i,j)到(n,m)的最长路。



那么把f[i][j]变成0的答案就是图中黄色格子向下走,红色格子向右走的答案取max。

最后把所有f[i][j]的答案取min即可。

代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2000+10;
#define gc() (p1 == p2 ? (p2 = buf + fread(p1 = buf, 1, 1 << 20, stdin), p1 == p2 ? EOF : *p1++) : *p1++)
#define read() ({ register int x = 0, f = 1; register char c = gc(); while(c < '0' || c > '9') { if (c == '-') f = -1; c = gc();} while(c >= '0' && c <= '9') x = x * 10 + (c & 15), c = gc(); f * x; })
char buf[1 << 20], *p1, *p2;
int a[maxn][maxn];
ll f[maxn][maxn],dp[maxn][maxn];
bool vis[maxn][maxn];
int n,m;
ll ans=0x3f3f3f3f3f3f3f3f;
struct node{
int x,y;
node(){}
node(int aa,int bb){
x=aa;
y=bb;
}
};
queue <node> q;
void Solve(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
scanf("%d",&a[i][j]);
}
}
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
dp[i][j]=max(dp[i-1][j],dp[i][j-1])+a[i][j];
}
}
for(int i=n;i;--i){
for(int j=m;j;--j){
f[i][j]=max(f[i+1][j],f[i][j+1])+a[i][j];
}
}
q.push(node(n,m));
while(!q.empty()){
node t=q.front();
if(vis[t.x][t.y]) continue;
vis[t.x][t.y]=1;
q.pop();
ll x=max(dp[t.x-1][t.y],dp[t.x][t.y-1]);
if(dp[t.x-1][t.y]>dp[t.x][t.y-1] && t.x>1 ) q.push(node(t.x-1,t.y));
else if(t.y>1) q.push(node(t.x,t.y-1));
}
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
if(vis[i][j]){
ll res=dp[n][m]-a[i][j];
for(int k=1;k<j;++k) res=max(res,dp[i][k]+f[i+1][k]);
for(int k=1;k<i;++k) res=max(res,dp[k][j]+f[k][j+1]);
ans=min(res,ans);
}
}
}
printf("%lld\n",ans);
}
int main(){
Solve();
return 0;
}

小集训模拟赛9 T4 步步为零

土题大战Vol.0 T2 小奇的矩阵 (火星补锅系列)

这题算是比较难的。首先需要推一下柿子(推柿子的时间和你上高考数学课划水的时间成正比)

当然,但凡你没有和我一样,高二快过一半,数学只有高一上的水平,就能一眼看出来,题目里面的柿子是个方差公式的变形。

然后,根据 \(D(x)=E(x^2)-(E(x))^2\) 这个学过高考都知道的柿子,就可以推出:

\(ans=(n+m-1)\sum_{i=1}^{n+m-1}A_i^2-(\sum_{i=1}^{n+m-1}A_i^2)^2\)

然后会发现,这个柿子的值只和每一项的值和每一项的平方有关。

于是可以定义转移方程:

dp[i][j][k]表示当前走到(i,j),\(\sum_{s=1}^{i+j-1}A_s\) 的值为k,的最小的\(\sum_{s=1}^{i+j-1}A_s^2\)

然后转移就很简单啦!

代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100000+10;
#define gc() (p1 == p2 ? (p2 = buf + fread(p1 = buf, 1, 1 << 20, stdin), p1 == p2 ? EOF : *p1++) : *p1++)
#define read() ({ register int x = 0, f = 1; register char c = gc(); while(c < '0' || c > '9') { if (c == '-') f = -1; c = gc();} while(c >= '0' && c <= '9') x = x * 10 + (c & 15), c = gc(); f * x; })
char buf[1 << 20], *p1, *p2;
ll dp[40][40][2000];
int a[40][40];
int n,m;
ll ans;
void Solve(){
int T;scanf("%d",&T);
while(T--){
ans=0x3f3f3f3f3f3f3f3f;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
scanf("%d",&a[i][j]);
}
}
memset(dp,0x3f,sizeof(dp));
dp[1][1][a[1][1]]=a[1][1]*a[1][1];
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
for(int k=a[i][j];k<=1800;++k){
if(i==1&&j==1) continue;
if(i>1&&j>1) dp[i][j][k]=min(dp[i][j-1][k-a[i][j]],dp[i-1][j][k-a[i][j]])+a[i][j]*a[i][j];
else if(j==1) dp[i][j][k]=dp[i-1][j][k-a[i][j]]+a[i][j]*a[i][j];
else dp[i][j][k]=dp[i][j-1][k-a[i][j]]+a[i][j]*a[i][j];
}
}
}
for(int i=0;i<=1800;++i) if(dp[n][m][i]<=1e9) ans=min(ans,1ll*(n+m-1)*dp[n][m][i]-1ll*i*i);
printf("%lld\n",ans);
}
}
int main(){
Solve();
return 0;
}

方阵里面的dp的更多相关文章

  1. 如果你的NavigationDrawer里面的Item没有响应,Drawer不能左滑关闭

    如果你的NavigationDrawer里面的Item没有响应,Drawer不能左滑关闭,应该是因为你没有把主要内容放在DrawerLayout标签下的第一位. The main content vi ...

  2. (转)android res文件夹里面的drawable(ldpi、mdpi、hdpi、xhdpi、xxhdpi)

    android res文件夹里面的drawable(ldpi.mdpi.hdpi.xhdpi.xxhdpi) (1)drawable-hdpi里面存放高分辨率的图片,如WVGA (480x800),F ...

  3. Activity往另外一个Activity传值,Fragment获取另外一个Activity里面的值。

    在oneActivity中实现跳转到MainActivity //intent 用来跳转另外一个MainActivity,bundle传值到MainActivity         Intent Ma ...

  4. Java基本概念(2)J2EE里面的2是什么意思

    J2EE里面的2是什么意思 J2SE,J2SE,J2ME中2的含义要追溯要1998年.1998年Java 1.2版本发布,1999年发布Java 1.2的标准版,企业版,微型版三个版本,为了区分这三个 ...

  5. 在wex5平台grid里面的gridselect下拉不能显示汉字问题

    当grid里面有gridSelect组件的时候,gridSelect里面的bind-ref是对应的数据库存入字段(int类型),bind-labelRef是对应的计算字段(视图里面的),而option ...

  6. dede文章调用时过滤调 body里面的style属性和值

    dede 发布文章的时候会在里面的标签中添加一些style 属性,现在改网站想去掉这些属性和里面的值,因为文章太多所以就用下面的方法 \include\arc.listview.class.php 在 ...

  7. 提取数据库字段里面的值,并改变+图片懒加载,jquery延迟加载

    要求:手机端打开某个页面的详细信息,因为网速或者别的原因,响应太慢,因为图片大的原因,希望先进来,图片在网页运行的情况再慢慢加载(jquer延迟加载) http://www.w3cways.com/1 ...

  8. JAVA里面的IO流(一)分类2(节点流和处理流及构造方法概要)

    IO流根据处理对象的不同分为节点流和处理流. 直接对文件进行处理的流为节点流: 对流进行包装从而实现对文件的优化处理的流为处理流. 节点流类型: 可以看出,节点流主要分这几大类: 文件流 文件流构造方 ...

  9. 头文件里面的ifndef /define/endif的作用

    c,c++里面,头文件里面的ifndef /define/endif的作用 今天和宿舍同学讨论一个小程序,发现有点地方不大懂······ 是关于头文件里面的一些地方: 例如:要编写头文件test.h ...

随机推荐

  1. Java 常用 Collection 继承关系与接口实现

    Java Collection List 接口 继承.接口实现关系: public interface List<E> extends Collection<E> 方法定义: ...

  2. C语言学习笔记---2.C语言数据类型

    1.C语言基本数据类型 1.1 int类型 int类型是有符号整型,即int类型的值必须是整数,可以是正整数.负整数或零.其取值范围依计算机系统而异.一般而言,储存一个int要占用一个机器字长. 声明 ...

  3. DFS模板

    DFS模板 题型分类:我们可以将DFS题分为两大类: 1 . 地图型:这种题型将地图输入,要求完成一定的任务.因为地图的存在.使得题意清楚形象化,容易理清搜索思路.AOJ 869-迷宫(遍历地图,四向 ...

  4. cnblogs-theme-silence 主题设置简约风格

    本文参考 更改博客皮肤 更改博客皮肤为Custom 页面定制CSS代码 勾选禁用模板默认CSS 导入复制该文件内容到代码框中 配置代码块复制功能 样式 和 右侧滑动条样式 /*复制功能添加按钮 beg ...

  5. C#导出数据—使用Word模板

    前言 本文主要介绍C#使用标签替换的方法导出数据,导出的数据模板使用Word文档. 模板建立 首先创建一个Word文档,然后建立一个基础模板.然后将上方菜单切换到插入菜单. 然后在想填充数据的地方添加 ...

  6. Java基础系列(28)- 方法的定义和调用

    方法的定义 Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法: 修饰符 返回值类型 方法名(参数类型 参数名){ -- 方法体 -- retu ...

  7. Docker系列(23)- CMD和ENTRYPOINT的区别

    CMD和ENTRYPOINT的区别 CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代 ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令 测试CMD ...

  8. django对layui中csrf_token处理方式及其它一些处理

    第一:由于layui官方是没有csrf_token处理机制,所以,在使用layui中post请求,请不要按layui官方提供的两种方法进行设置 官方设置如下: table.render({ elem: ...

  9. SpringSecurity系列学习(一):初识SpringSecurity

    SpringSecurity Spring Security是spring采用AOP思想,基于servlet过滤器实现的安全框架.它提供了完善的认证机制和方法级的 授权功能.是一款非常优秀的权限管理框 ...

  10. hdu5909-Tree Cutting【FWT】

    正题 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5909 题目大意 给出\(n\)和\(m\)(\(m=2^k\)).再给出一个大小为\(n\)的树 ...