Luogu-P2295 MICE

 

topic

Topic Link

 

 

Test score:  100

 

 

 

The main algorithm: memory search, dynamic programming

 

 

Casual working:

  There aftereffect of DP?

 analysis

  Pseudo-memory search:

    Consider the special circumstances of the starting point, pre-processing
    Dfs seized answer every time to see the path of the mouse, plus the number of mice, the mice mouse to see the number of points where the deleted
    remember the final score 40 points back

  Code

#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 */

 

总结:

   确定动规模型

 

Guess you like

Origin www.cnblogs.com/SeanOcean/p/11366054.html