寒假Day3

寒假Day3

一、动态规划
1.小a和uim之大逃离

题目描述
瞬间,地面上出现了一个n*m的巨幅矩阵,矩阵的每个格子上有一坨0~k不等量的魔液。怪物各给了小a和uim一个魔瓶,说道,你们可以从矩阵的任一个格子开始,每次向右或向下走一步,从任一个格子结束。开始时小a用魔瓶吸收地面上的魔液,下一步由uim吸收,如此交替下去,并且要求最后一步必须由uim吸收。魔瓶只有k的容量,也就是说,如果装了k+1那么魔瓶会被清空成零,如果装了k+2就只剩下1,依次类推。怪物还说道,最后谁的魔瓶装的魔液多,谁就能活下来。小a和uim感情深厚,情同手足,怎能忍心让小伙伴离自己而去呢?沉默片刻,小a灵机一动,如果他俩的魔瓶中魔液一样多,不就都能活下来了吗?小a和他的小伙伴都笑呆了!
现在他想知道他们都能活下来有多少种方法。

一个整数,表示方法数。由于可能很大,输出对1 000 000 007取余后的结果。
f[i][j][p][q]表示他们走到(i,j),且两人魔瓶内魔液量的差为p时的方法数。q=0表示最后一步是小a走的,q=1表示最后一步是uim走的。题目中说魔瓶的容量为k,实际上就是动归时p需要对k+1取余数,即p只有0~k,k+1种可能。答案为所有f[i][j][0][1]的和。
动归方程如下:(为了方便已经令k=k+1)
f[i][j][p][0]+=f[i-1][j][(p-mapp[i][j]+k)%k][1] (i-1>=1)
f[i][j][p][0]+=f[i][j-1][(p-mapp[i][j]+k)%k][1] (j-1>=1)
f[i][j][p][1]+=f[i-1][j][(p+mapp[i][j])%k][0] (i-1>=1)
f[i][j][p][1]+=f[i][j-1][(p+mapp[i][j])%k][0] (j-1>=1)

for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
        for(int h=0;h<K;h++){
            if(i+1<=n){
                f[i+1][j][(h+a[i+1][j])%K][0]=(f[i+1][j][(h+a[i+1][j])%K][0]+f[i][j][h][1])%Mod;
                f[i+1][j][(h-a[i+1][j]+K)%K][1]=(f[i+1][j][(h-a[i+1][j]+K)%K][1]+f[i][j][h][0])%Mod;
              }
            if(j+1<=m){
                f[i][j+1][(h+a[i][j+1])%K][0]=(f[i][j+1][(h+a[i][j+1])%K][0]+f[i][j][h][1])%Mod;
                f[i][j+1][(h-a[i][j+1]+K)%K][1]=(f[i][j+1][(h-a[i][j+1]+K)%K][1]+f[i][j][h][0])%Mod;
              }
            if(h==0)ans=(ans+f[i][j][h][1])%Mod;
          }
  1. 赛斯石
    题目描述
    现需上市Need Need Need 赛斯重量的赛斯石,卖家想算出这些赛斯石经过某种合并方式来获得的最大收益。然而目前有一个问题,市场在真程大殿附近(真程海洋中心位置),卖家需要租船送赛斯石过去(即不考虑卖家自己租船过去的费用),目前有十种船可以租,载重量从1si 1si 1si 到10si 10si 10si ,每艘船的租价也是有所不同的,如下表所示:
    由于真程大殿附近有强烈的赛斯力,导致无法对赛斯石进行任何操作,商家将赛斯石运过来之后就只能按照之前合并好的卖。假设卖家不返回,且这些赛斯石全部能卖出去。现在卖家他要计算总盈利(设总盈利=赛斯石的总收益-租船所需总费用),请你设计一个程序,算出一种最佳方案,以获得最大总盈利。
for(int i=1;i<=t;i++)
      for(int j=1;j<=10;j++)
        if(i-j>=1)                                           
           solution[i]=max(solution[i],solution[i-j]+solution[j]);                

    if(t<=10)
       cout<<solution[t]+1;                 
    else cout<<solution[t];

3 .猫狗大战

题目描述
新一年度的猫狗大战通过SC(星际争霸)这款经典的游戏来较量,野猫和飞狗这对冤家为此已经准备好久了,为了使战争更有难度和戏剧性,双方约定只能选择Terran(人族)并且只能造机枪兵。
比赛开始了,很快,野猫已经攒足几队机枪兵,试探性的发动进攻;然而,飞狗的机枪兵个数也已经不少了。野猫和飞狗的兵在飞狗的家门口相遇了,于是,便有一场腥风血雨和阵阵惨叫声。由于是在飞狗的家门口,飞狗的兵补给会很快,野猫看敌不过,决定撤退。这时飞狗的兵力也不足够多,所以没追出来。
由于不允许造医生,机枪兵没办法补血。受伤的兵只好忍了。555-
现在,野猫又攒足了足够的兵力,决定发起第二次进攻。为了使这次进攻给狗狗造成更大的打击,野猫决定把现有的兵分成两部分,从两路进攻。由于有些兵在第一次战斗中受伤了,为了使两部分的兵实力平均些,分的规则是这样的:1)两部分兵的个数最多只能差一个;2)每部分兵的血值总和必须要尽可能接近。现在请你编写一个程序,给定野猫现在有的兵的个数以及每个兵的血格值,求出野猫按上述规则分成两部分后每部分兵的血值总和。

用一个Bool类型的DP
dp[i][j][k] i表示第一对的血量总数j第二对的血量总数k表示相差人数。
只有两种选择要么被一对选要么对二队选

dp[0][0][0]=1;
    for(i=1;i<=n;i++){
        scanf("%d",&h[i]);
        sum+=h[i];
        for(p=sum-h[i];p>=0;p--)
            for(k=10;k>=0;k--){
              s=sum-h[i]-p;
              if(dp[p][s][k]){
                  dp[p+h[i]][s][k+1]=1;
                  if(k>0)
                      dp[p][s+h[i]][k-1]=1;
                  else
                      dp[s+h[i]][p][1]=1;
              }
          }
    }

4.不等式数列

不等式序列 将1到n任意排列,然后在排列的每两个数之间根据他们的大小关系插入“>”和“<”。问在所有排列中,
有多少个排列恰好有k个“<”。答案对2015取模。 注:1~n的排列指的是1~n这n个数各出现且仅出现一次的数列。

#include<bits/stdc++.h>
#define Mod 2015
using namespace std;
int n,k;
int dp[1500][1500];
int main(){
    cin>>n>>k;
    for(int i=1;i<=n;i++)
        dp[i][0]=dp[i][i-1]=1;   
    for(int i=2;i<=n;i++)
        for(int j=1;j<=min(i-1,k);j++){
            dp[i][j]=(dp[i-1][j-1]*(i-j)+dp[i-1][j]*(j+1))%Mod;
        }
    cout<<dp[n][k]<<endl;
    return 0;
}

dp[i][j]表式前i个数j个减号的方案数
当排列插入原数列时,当插入的位置是j+1的位置时减号的个数不需要加可以保持原数,还有i-j的位置时减号的个数需要+1
所以可以得出状态转移方程 dp[i][j]=(dp[i-1][j-1](i-j)+dp[i-1][j](j+1))%Mod;
5.经营与开发

4X概念体系,是指在PC战略游戏中一种相当普及和成熟的系统概念,得名自4个同样以“EX”为开头的英语单词。
eXplore(探索) eXpand(拓张与发展) eXploit(经营与开发) eXterminate(征服) ——维基百科
今次我们着重考虑exploit部分,并将其模型简化: 你驾驶着一台带有钻头(初始能力值w)的飞船,按既定路线依次飞过n个星球。
星球笼统的分为2类:资源型和维修型。(p为钻头当前能力值)
1. 资源型:含矿物质量a[i],若选择开采,则得到a[i]p的金钱,之后钻头损耗k%,即p=p(1-0.01k)
2. 维修型:维护费用b[i],若选择维修,则支付b[i]p的金钱,之后钻头修复c%,即p=p(1+0.01c)
注:维修后钻头的能力值可以超过初始值(你可以认为是翻修+升级) 请作为舰长的你仔细抉择以最大化收入。 【输入格式】 第一行4个整数n,k,c,w。 以下n行,每行2个整数type,x。 type为1则代表其为资源型星球,x为其矿物质含量a[i];
type为2则代表其为维修型星球,x为其维护费用b[i]; 【输出格式】 一个实数(保留2位小数),表示最大的收入。

k=1-0.01*k;c=1+0.01*c;
    for(int i=1;i<=n;i++) scanf("%d%d",&t[i],&a[i]);
    for(int i=n;i;i--)
        if (t[i]==1)
            ans=max(ans,ans*k+a[i]);
        else
            ans=max(ans,ans*c-a[i]);
    printf("%.2lf\n",ans*w);

正难则反,F[i]表示第i–n个星球的最优收入,且假设从第i个星球开始时钻头能力为1。换句话说,这样的状态设计,规定了一个参考系。
转移过程就变得简单:如果在第i个星球开采,那么第i+1–n个星球的初始钻头能力就是1*(1-0.01k)。换句话说,就是F[i+1]*(1-0.01k)。
所以F[i]=max{F[i+1],F[i+1]*(1-0.01k)+a[i]}
对于维护型星球,大同小异。就系数和代价的正负而已。
观察方程,F[i]=max{F[i+1],F[i+1]*(1-0.01k)+a[i]}
实际上就是取下i+1–n的最值而已,所以这题实际上就成了贪心。

6.Treasure Chest

贝西和伯尼找到了一个装满了金币的宝箱!但是,作为奶牛,他们不能随便进入一家商店去买东西。所以他们决定去用这些金币玩一个游戏。
这里有N(1<=N<=5000)个硬币,每个都有一个价值C_i(1<=C_i<=5000)。这些硬币被摆成了一行。贝西和伯尼每人一回合。到了一只奶牛的回合时,他就要拿走最左边或者最右边的硬币。当没有硬币时,游戏结束。
贝西和伯尼都想要使自己拿到的金币价值尽量高,贝西先拿。现在贝西想要你帮帮她,算出她最多可以拿多少钱(伯尼也会尽量取到最优)。

for(int i=1;i<=n;i++){
        cin>>c[i];
        H[i]+=H[i-1]+c[i];
        dp[i][i]=c[i];
    }
    for(int i=n-1;i>=1;i--)
        for(int j=i+1;j<=n;j++){
            dp[i][j]=max(H[j]-H[i-1]-dp[i+1][j],H[j]-H[i-1]-dp[i][j-1]);
        }
    cout<<dp[1][n];

dp[i][j]表示i和j之间的最大值

7.新魔法药水

题目描述
商店里有N种药水,每种药水都有一个售价和回收价。小S攒了V元钱,还会M种魔法,可以把一些药水合成另一种药水。他一天可以使用K次魔法,问他一天最多赚多少钱?
输入输出格式
输入格式:
第一行四个数N、M、V、K
接下来N行,每行两个数,表示药水的售价和回收价。
接下来M行,每行若干个数,第一个数表示魔法的成品,第二个数是原料的种数,接下来为各种原料的编号
输出格式:
一个数,表示小S的最大利润

巨火恶心题DP和dwq想了一晚上都没有想出来
还正在思考

#include<cstdio>
#define int long long
const int N=65,M=245,V=1005,K=35,inf=1e9;
int dp[K][V];//dp[i][j] means the max dollars we can get after using i times magic ans j dollars.
int method[N][M][N],cme[N][M],ccme[N];
int now[N][M][N],cn[N][M],ccn[N];
int in[N],out[N];
int n,m,vv,k;
int v[N],w[N];
inline void copp()
{
    int i,j,k;
    for(i=1;i<=n;i++)
    {
        ccn[i]=ccme[i];
        for(j=1;j<=ccn[i];j++)
        {
            cn[i][j]=cme[i][j];
            for(k=0;k<=cn[i][j];k++)
                now[i][j][k]=method[i][j][k];
        }
    }
    return;
}
signed main()
{
    int i,j,l,a,sum;
    scanf("%lld%lld%lld%lld",&n,&m,&vv,&k);
    for(i=1;i<=n;i++)
        scanf("%lld%lld",&in[i],&out[i]);
    for(i=1;i<=m;i++)
    {
        sum=0;
        scanf("%lld",&a);
        ccme[a]++;
        scanf("%lld",&cme[a][ccme[a]]);
        for(j=1;j<=cme[a][ccme[a]];j++)
            scanf("%lld",&method[a][ccme[a]][j]),sum+=in[method[a][ccme[a]][j]];
        method[a][ccme[a]][0]=sum;
    }
    copp();
    int cishu=1,mn,jmn;
    for(i=1;i<=n;i++)
    {
        mn=inf;
        for(j=1;j<=ccme[i];j++)
            if(method[i][j][0]<mn)
                mn=method[i][j][0],jmn=j;
        v[i]=mn;
        w[i]=out[i]-mn;
    }
    for(i=1;i<=k;i++)
        for(j=1;j<=n;j++)
            for(l=vv;l>=v[j];l--)
                if(dp[i][l]<dp[i-cishu][l-v[j]]+w[j])
                    dp[i][l]=dp[i-cishu][l-v[j]]+w[j];
    int mx,jmx[10];
    bool flag=0;
    for(cishu++;cishu<=m;cishu++)
    {
        for(i=1;i<=n;i++)
        {
            mx=0;flag=0;
            for(j=1;j<=ccn[i];j++)
            {
                for(l=1;l<=cn[i][j];l++)
                {
                    for(int jxc=1;jxc<=ccme[now[i][j][l]];jxc++)
                        if(mx<in[now[i][j][l]]-method[now[i][j][l]][jxc][0])
                            mx=in[now[i][j][l]]-method[now[i][j][l]][jxc][0],jmx[0]=now[i][j][l],jmx[1]=jxc,flag=1,jmx[2]=j,jmx[3]=l;
                }
            }
            if(!flag)
            {
                v[i]=inf;
                w[i]=-inf;
                continue;
            }
            now[i][jmx[2]][0]-=mx;
            now[i][jmx[2]][jmx[3]]=method[jmx[0]][jmx[1]][1];
            for(int lsk=2;lsk<=cme[jmx[0]][jmx[1]];lsk++)
                now[i][jmx[2]][++cn[i][jmx[2]]]=method[jmx[0]][jmx[1]][lsk];
            v[i]=now[i][jmx[2]][0];
            w[i]=out[i]-v[i];
        }
        for(i=cishu;i<=k;i++)
            for(j=1;j<=n;j++)
                for(l=vv;l>=v[j];l--)
                    if(dp[i][l]<dp[i-cishu][l-v[j]]+w[j])
                        dp[i][l]=dp[i-cishu][l-v[j]]+w[j];
    }
    printf("%lld\n",dp[k][vv]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值