码迷,mamicode.com
首页 > 其他好文 > 详细

[总结+题解]20150606

时间:2015-07-28 17:56:09      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:

// 此博文为迁移而来,写于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;
}
----------------------------------------------------------------------------------------------------

[总结+题解]20150606

标签:

原文地址:http://www.cnblogs.com/jinkun113/p/4682893.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!