动态规划学习——赢得最大数

本文讨论了一种基于递归和动态规划的纸牌游戏策略,分析了先手和后手如何通过选择左右纸牌最大化或最小化自己的得分。作者展示了三种方法:直接递归、带有缓存的递归和动态规划,以解决两人聪明人玩纸牌游戏的问题。
摘要由CSDN通过智能技术生成

题目:

给一个数组,表示纸牌,每张纸牌有一定的大小
两个人依次选择左边或者右边的纸牌,获得相应的点数
最后点数较大的为胜者
注:两个人都是聪明人,意味着拿牌会选择让自己获得更多的,让对方获得更少的选择

代码如下:

//给一个数组,表示纸牌,每张纸牌有一定的大小
//两个人依次选择左边或者右边的纸牌,获得相应的点数
//最后点数较大的为胜者
//注:两个人都是聪明人,意味着拿牌会选择让自己获得更多的,让对方获得更少的选择
#include<iostream>
#include<algorithm>
using namespace std;
int arr[10000];
int N;
int first1(int L,int R);
int second1(int L,int R);
int first2(int L,int R);
int second2(int L,int R);
int ways2_first[10000][10000];
int ways2_second[10000][10000];
int ways3_first[10000][10000];
int ways3_second[10000][10000];

//法一:直接递归
int ways1()
{
    int first=first1(0,N-1);
    int second=second1(0,N-1);
    return max(first,second);
}

//先手函数
//先手有两个选择,一是拿左边的纸牌,则其点数为arr[L]+second1(L+1,R);二是拿右边的牌,则其点数为arr[R]+second1(L,R-1)
//而最终的选择是让自己的点数尽可能大,所以用max求最大值
int first1(int L,int R)
{
    if(L==R) return arr[L];
    else{
        int t1=arr[L]+second1(L+1,R);
        int t2=arr[R]+second1(L,R-1);
        return max(t1,t2);
    }
}
//后手函数
//后手只能等待对方拿纸牌,而对方可以拿左边也可以拿右边的,最终对方要让后手拿到的点数尽可能小,所以用min函数求最小值
int second1(int L,int R)
{
    if(L==R) return 0;
    else{
        int t1=first1(L+1,R);
        int t2=first1(L,R-1);
        return min(t1,t2);
    } 
}

//法二:带有缓存的递归
int ways2()
{
    //初始化
    int i,j;
    for(i=0;i<=N;i++)
        for(j=0;j<=N;j++)
        { //注意这里不要掉了括号,因为这个调试了半天
            ways2_first[i][j]=-1;
            ways2_second[i][j]=-1;
        }
    int first=first2(0,N-1);
    int second=second2(0,N-1);
    return max(first,second);
}

int first2(int L,int R)
{
    int ans=0;
    if(ways2_first[L][R]!=-1) return ways2_first[L][R];
    else{
        if(L==R) ans=arr[L];
        else{
            int t1=arr[L]+second2(L+1,R);
            int t2=arr[R]+second2(L,R-1);
            ans=max(t1,t2);
        }
        ways2_first[L][R]=ans;
    }
    return ans;
}

int second2(int L,int R)
{
    int ans=0;
    if(ways2_second[L][R]!=-1) return ways2_second[L][R];
    else{
        if(L==R) ans=0;
        else{
            int t1=first2(L+1,R);
            int t2=first2(L,R-1);
            ans=min(t1,t2);
        }
        ways2_second[L][R]=ans;
    }
    return ans;
}

//法三:动态规划
int ways3()
{
    int i;
    for(i=0;i<N;i++){
        ways3_first[i][i]=arr[i];
        ways3_second[i][i]=0;
    }
    for(int startcol=1;startcol<N;startcol++){ 
        int L=0;
        int R=startcol;
        while(R<N){
            ways3_first[L][R]=max(arr[R]+ways3_second[L][R-1],arr[L]+ways3_second[L+1][R]);
            ways3_second[L][R]=min(ways3_first[L][R-1],ways3_first[L+1][R]);
            L++;
            R++;
        }
    }
    return max(ways3_first[0][N-1],ways3_second[0][N-1]);
}


int main()
{
    int choice=0;
    do{
        cout<<"请输入数组长度:"<<endl;
        cin>>N;
        int i=0;
        cout<<"请输入数组中每个数的值"<<endl;
        for(i=0;i<N;i++) cin>>arr[i];
        int result1=ways1();
        cout<<"法一 直接递归 的结果为 "<<result1<<endl;
        int result2=ways2();
        cout<<"法二 缓存递归 的结果为 "<<result2<<endl;
        int result3=ways3();
        cout<<"法三 动态规划 的结果为 "<<result3<<endl;



        cout<<"继续请输入1"<<endl;
        cin>>choice;
    }while(choice==1);
    return 0;
}

参考资料:

bilibili 马士兵教育——左程云

【应B友要求火速上线!算法大神(左程云)教你从暴力递归到动态规划,吊打所有暴力递归、动态规划问题】https://www.bilibili.com/video/BV1ET4y1U7T6?p=13&vd_source=4e9b7dd8105df854ae96830c97920252

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 微软创建NT操作系统的历史可谓观止。NT操作系统是微软自1980年代中期开始开发的,经过多年的努力和完善,最终在1993年发布了第一个正式版本。NT操作系统以其稳定、高效和安全的特性,成为了微软在企业领域最重要的操作系统之一。 NT操作系统的成功给了微软一个稳定发展的基础,也推动了微软在未来的夺命狂奔。夺命狂奔是指在竞争激烈的软件市场上,为了保持领先地位而不断开发和发布新产品,微软通过不断创新和改进赢得了市场份额。 微软未来的夺命狂奔可以从它近年来推出的产品和服务中看出端倪。微软积极推广云计算服务Azure,这是一个强大的云平台,为企业提供了灵活、安全和可靠的解决方案。此外,微软还致力于发展人工智能技术,如语音识别、自然语言处理和机器学习等。这些创新不仅扩大了微软在企业市场的影响力,也增加了其全球用户的多样化需求。 微软在夺命狂奔中所面临的挑战也不容忽视。随着移动设备的普及,微软需要实现与iOS和Android等主流操作系统的兼容性,以保持在移动市场的竞争力。此外,随着开源软件的兴起,微软也需要适应这一趋势,积极参与开源社区,推动开源软件的发展。 总之,微软创建NT操作系统和未来的夺命狂奔展现了微软在软件行业的实力和潜力。通过持续的创新和不断进化,微软将继续在企业和消费者市场中扮演重要角色。 ### 回答2: 《观止:微软创建NT和未来的夺命狂奔》是一部以微软公司创造Windows NT操作系统和未来发展的故事为背景的电影。这个故事主要讲述了微软在当时面临的技术挑战、市场竞争和公司发展的困境,并展现了他们的不断努力和创新精神。 微软创建Windows NT操作系统的过程是一段充满曲折和艰辛的旅程。在那个时代,微软面对着Unix操作系统的垄断地位和其它竞争对手的激烈竞争。为了突破操作系统的技术限制和摆脱对其他公司的依赖,微软决定自己开发一款全新的操作系统。于是,他们成立了一个专门的团队,经过不断的研发和测试,最终诞生了Windows NT操作系统。 《观止:微软创建NT和未来的夺命狂奔》还聚焦于微软的未来发展。随着Windows NT的问世,微软成功地抓住了市场机遇,并成为全球最大的软件公司之一。电影展示了微软团队在公司内部的斗争和外部环境的变化。他们不断推出更新版本的Windows操作系统,提供更多的功能和更好的用户体验,以保持竞争优势。 此外,电影也揭示了微软面临的挑战和反思。他们在垄断调查和法律纷争中面临着巨大压力,并被要求在竞争和创新方面采取更加公平的做法。微软也通过收购和战略合作来扩大业务领域,尝试进军互联网和移动领域。然而,他们也面临着来自谷歌等公司的新兴竞争对手的挑战。 《观止:微软创建NT和未来的夺命狂奔》通过展示微软在创造和发展Windows NT操作系统过程中的挑战和努力,向我们展示了一个科技巨头如何在激烈的竞争中不断进步和寻求发展机遇。这部电影激励着观众们,鼓舞他们在面对困难和竞争时坚持创新和努力,并为未来的夺命狂奔奠定基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云霄星乖乖的果冻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值