• [考试]20150606


    // 此博文为迁移而来,写于2015年6月7日,不代表本人现在的观点与看法。原始地址:http://blog.sina.com.cn/s/blog_6022c4720102w3bs.html

     

    1、前言
           今天考试状态稍微好一点,错的地方和动态规划本身没有太大关系(然而没写高精度直接扣60分是不是太血腥= =)。其实我觉得今天题目好水。。。我都觉得水了。
    2、题目


    分析:根据双方的能量和当前回合数确定状态。设 f[i][j][k] 表示当前第 i 回合,A 有 j 点能量,B 有 k 点能量有的游戏局面数。若某方选择攻击,另一方必定选择攻击或防御。把攻击、防御、充能所有情况全部用A和B的能量变化量来体现,方程很容易写出,比较复杂,直接看代码。
    代码:
    -----------------------------------------------------------------------------------------------------
    #include<cstdio>
    #define MOD 1000000007
    #define MAXN 205
    #define PLUS(p) f[k][i][j]+=p
     
    int n,k,i,j;
    long long f[MAXN][MAXN][MAXN],ans;
     
    int main()
    {
            freopen("bbj.in","r",stdin);
            freopen("bbj.out","w",stdout);
            scanf("%d",&n); 
            f[0][0][0]=1;
            for (int k=1;k<=n;k++)
                    for (int i=0;i<=k;i++)
                            for (int j=0;j<=k;j++)
                            {
                                    if (i<k && j<k) PLUS(f[k-1][i][j]); if (i<k-1 && j<k-1) PLUS(f[k-1][i+1][j+1]);  
                                    if (i<k-1 && j<k) PLUS(f[k-1][i+1][j]);  if (i<k && j<k-1) PLUS(f[k-1][i][j+1]);
                                    if (i && j) PLUS(f[k-1][i-1][j-1]); if (i && j<k) PLUS(f[k-1][i-1][j]);  
                                    if (i<k && j) PLUS(f[k-1][i][j-1]); 
                                    f[k][i][j]%=MOD;
                            }
            for (int i=0;i<=n;i++)
                    for (int j=0;j<=n;j++)
                    {
                            ans+=f[n][i][j]; ans%=MOD;
                    }
            printf("%d",ans);
            return 0
    }
    ----------------------------------------------------------------------------------------------------
    注意:需要开long long。
     


    分析:先讲yxj的正解。f[i][j]表示起点到(i,j)的最短路,按列转移。这固然可以,但是我大概看了一下所有AC的代码没有一个是跑的最短路,所以接下来我来讲讲各种奇怪的做法。方法二:由于这道题可以向上走,所以这并不能直接从上从左来转移。同样我们还是定义f[i][j]表示起点到(i,j)的距离,然而我们注意到最左边的一列必定由上至下到达(因为不能向左走),所以先求出来;然后从左至右按列转移,首先我们先假设不能向上走,即普通的棋盘型DP,然后我们将当前那一列从上至下,再从下至上进行数据更新(即能够向上走所得到的更优解),即:f[i][j]=min(f[i][j-1],f[i-1][j],f[i+1][j])+map[i][j]。我就是这么做的,下面的代码也就是这样的,开始我觉得这种想法有问题,但是我问了yxj他说应该可以。。。那就好。还有用线段树维护的,此处省略。
     
    代码:
    ----------------------------------------------------------------------------------------------------
    #include<cstdio>
    #include<cstring>
    #define MAXN 1005
    #define INF 0x7f7f7f7f
     
    typedef long long ll;
     
    ll min(ll a,ll b) { return (a<b)?a:b; }
     
    ll n,m,map[MAXN][MAXN],f[MAXN][MAXN];
     
    int main()
    {
            freopen("walk.in","r",stdin); 
            freopen("walk.out","w",stdout);
            scanf("%I64d %I64d",&n,&m);
            memset(f[0],INF,sizeof(f[0]));
            memset(f[n+1],INF,sizeof(f[n+1]));
            f[0][1]=0;
            for (ll i=1;i<=n;i++)
                    for (ll j=1;j<=m;j++) scanf("%I64d",&map[i][j]);
            for (ll i=1;i<=n;i++) f[i][1]=f[i-1][1]+map[i][1];
            for (ll j=2;j<=m;j++) 
            {
                    for (ll i=1;i<=n;i++)   f[i][j]=min(f[i][j-1],f[i-1][j])+map[i][j];
                    for (ll i=n;i>=1;i--)     f[i][j]=min(f[i+1][j]+map[i][j],f[i][j]);  
                    for (ll i=1;i<=n;i++)   f[i][j]=min(f[i+1][j]+map[i][j],f[i][j]);
            }
            printf("%I64d",f[n][m]);
            return 0;
    }
    ----------------------------------------------------------------------------------------------------
     


    分析:最水的一道题啦。。。我就抱着这样的心态把他第一个给做完了,然而江哥这个#%#¥%@#。。。我开了 long long 然而这并不行。。。要写高精度存储!方程略,裸棋盘型DP。
     
    代码:
    ----------------------------------------------------------------------------------------------------
    #include<cstdio>
    #define MAXN 1005
     
    int max(int a,int b) { return (a>b)?a:b; }
     
    int n,m,map[MAXN][MAXN];
    long long f[MAXN][MAXN];
     
    int main()
    {
            freopen("path.in","r",stdin);
            freopen("path.out","w",stdout);
            scanf("%d %d",&n,&m);
            for (int i=1;i<=n;i++)
                    for (int j=1;j<=m;j++) scanf("%d",&map[i][j]);
            f[0][1]=1;
            for (int i=1;i<=n;i++)
                    for (int j=1;j<=m;j++)
                    {
                            if (map[i][j]) continue;
                            if (!map[i-1][j]) f[i][j]+=f[i-1][j];
                            if (!map[i][j-1]) f[i][j]+=f[i][j-1];
                    }
            printf("%I64d",f[n][m]);
            return 0;
    }
    ----------------------------------------------------------------------------------------------------
     
     

    分析:这道题是这次考试最麻烦的,我只搞出了30分的暴力。看了题解,这道题还是需要用到许多和数学相关的东西,我们慢慢来分析一下,如下图(公式比较多,直接放在图片上算了)
     


    代码:
    ----------------------------------------------------------------------------------------------------
    #include<cstdio>
    #define MAXN 1005
    #define MOD 1000000007
    #define DFS_next if (y==n) DFS(x+1,1); else DFS(x,y+1)
    typedef long long ll;
     
    ll ans,n,fac[MAXN]={1},c[MAXN][MAXN],f[MAXN]={1};
     
    void DP()
    {
            for (ll i=0;i<=n;i++)
            for (ll j=0;j<=i;j++)
            if (!j) c[i][j]=1;
            else c[i][j]=(c[i-1][j-1]+c[i-1][j])%MOD; 
            for (ll i=1;i<=n;i++) fac[i]=(fac[i-1]*i)%MOD; 
            for (ll i=1;i<=n;i++)
            {
                    for (ll j=0;j<=i;j++) f[i]=(f[i]+c[i][j]*c[i][j]%MOD*fac[j])%MOD;
                    f[i]=(f[i]*f[i])%MOD;
                    for (ll j=1;j<=i;j++) 
                    {
                            ll tc=(c[i][j]*c[i][j])%MOD;
                            tc=(tc*fac[j])%MOD;
                            tc=(tc*f[i-j])%MOD;
                            f[i]-=tc;
                            f[i] =(f[i]+MOD)%MOD; 
                    }
            }
    }
     
    int main()
    {
            freopen("chessboard.in","r",stdin);
            freopen("chessboard.out","w",stdout);
            scanf("%d",&n);
            DP();
            printf("%d",f[n]);
            return 0;
    }
    ----------------------------------------------------------------------------------------------------
  • 相关阅读:
    [css3]搜索框focus时变长
    [css3]文字过多以省略号显示
    HTML5表单新增属性
    [JS]getYear()和getFullYear()方法区别
    红包彩带动画效果
    ios下input focus弹出软键盘造成fixed元素位置移位
    旋转效果
    移动端前端开发
    如何加快页面加载速度
    centos7/rhel7下安装redis4.0集群
  • 原文地址:https://www.cnblogs.com/jinkun113/p/4682893.html
Copyright © 2020-2023  润新知