Luogu-P2295 MICE
Posted seanocean
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu-P2295 MICE相关的知识,希望对你有一定的参考价值。
题目
测试得分: 100
主要算法 : 记忆化搜索,动态规划
题干:
有后效性DP?
分析
伪记忆化搜索:
考虑起点的特殊情况,预先处理
Dfs搜出答案,每一次路径看到的老鼠,加上老鼠数目,把看到的老鼠数目所在点的老鼠删除掉
记得回溯最终得分40分
代码
#include<stdio.h> #include<stdlib.h> #include<string.h> #define FORa(i,s,e) for(int i=s;i<=e;i++) #define FORs(i,s,e) for(int i=s;i>=e;i--) #define gc getchar()//pa==pb&&(pb=(pa=buf)+fread(buf,1,100000,stdin),stdin)?EOF:*pa++ #define File(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout); using namespace std; char buf[100000],*pa,*pb; inline int read(); const int N=1100,M=1100,INF=2147483647; int n,m,a[N+1][M+1],s[N+1][M+1],f[N+1][M+1][2]; int ans=INF,mx[]=0,1,-1,0,my[]=1,0,0,-1; inline int min(int fa,int fb)return fa<fb?fa:fb; void Init() n=read(),m=read(); FORa(i,1,n) FORa(j,1,m) a[i][j]=read(); void Dfs(int x,int y,int cnt) if(s[x][y]<cnt||cnt>=ans) return; s[x][y]=cnt; if(x==n&&y==m) ans=min(cnt,ans); return; int fx,fy,p[4]; FORa(i,0,1) fx=x+mx[i],fy=y+my[i]; if(fx<=n&&fy<=m) FORa(k,0,3) p[k]=a[fx+mx[k]][fy+my[k]],a[fx+mx[k]][fy+my[k]]=0; Dfs(fx,fy,cnt+p[0]+p[1]+p[2]+p[3]); FORa(k,0,3) a[fx+mx[k]][fy+my[k]]=p[k]; void Solve_BL() memset(s,127,sizeof(s)); int cnt=a[1][1]+a[1][2]+a[2][1]; a[1][2]=a[2][1]=a[1][1]=0; Dfs(1,1,cnt); printf("%d",ans); int main() Init(); Solve_BL(); return 0; inline int read() register char c(gc);register int f(1),x(0); while(c<‘0‘||c>‘9‘) f=c==‘-‘?-1:1,c=gc; while(c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=gc; return x*f; /* 5 5 86 19 26 18 92 25 67 69 28 83 54 56 7 5 93 63 33 8 66 91 68 74 56 92 90 */
100分DP
定义:
a[i][j]表示格子(i,j)中老鼠的数量。
f[i][j][0]表示当前小象位于格子(i,j)且上一个位置是(i-1,j)所看见的老鼠的最少数量。
f[i][j][1]表示当前小象位于格子(i,j)且上一个位置是(i,j-1)所看见的老鼠的最少数量
我们可以得到转移方程:
f[i][j][0]=min(f[i-1][j][0]+a[i][j-1],f[i-1][j][1])+a[i+1][j]+a[i][j+1]
f[i][j][1]=min(f[i][j-1][0],f[i][j-1][1]+a[i-1][j])+a[i+1][j]+a[i][j+1]
最后答案为 min(f[n][m][0],f[n][m][1])。 复杂度:O(N*M)。
#include<stdio.h> #include<stdlib.h> #include<string.h> #define FORa(i,s,e) for(int i=s;i<=e;i++) #define FORs(i,s,e) for(int i=s;i>=e;i--) #define gc getchar()//pa==pb&&(pb=(pa=buf)+fread(buf,1,100000,stdin),stdin)?EOF:*pa++ #define File(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout); using namespace std; char buf[100000],*pa,*pb; inline int read(); const int N=1100,M=1100; int n,m,f[N+1][M+1][2],a[N+1][M+1]; inline int min(int fa,int fb)return fa<fb?fa:fb; void Solve_Dp() memset(f,63,sizeof(f)); n=read(),m=read(); FORa(i,1,n) FORa(j,1,m) a[i][j]=read(); f[1][1][0]=f[1][1][1]=a[1][1]+a[1][2]+a[2][1]; FORa(i,1,n) FORa(j,1,m) if(i*j!=1) f[i][j][0]=min(f[i][j-1][0]+a[i-1][j],f[i][j-1][1])+a[i+1][j]+a[i][j+1]; f[i][j][1]=min(f[i-1][j][1]+a[i][j-1],f[i-1][j][0])+a[i+1][j]+a[i][j+1]; printf("%d\\n",min(f[n][m][0],f[n][m][1])); int main() File("lemouse"); Solve_Dp(); return 0; inline int read() register char c(gc);register int f(1),x(0); while(c<‘0‘||c>‘9‘) f=c==‘-‘?-1:1,c=gc; while(c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=gc; return x*f; /* 5 5 86 19 26 18 92 25 67 69 28 83 54 56 7 5 93 63 33 8 66 91 68 74 56 92 90 */
总结:
确定动规模型
以上是关于Luogu-P2295 MICE的主要内容,如果未能解决你的问题,请参考以下文章