zoukankan      html  css  js  c++  java
  • 【NOIP2010】乌龟棋

    本题在洛谷上的链接:https://www.luogu.org/problemnew/show/P1541


    呃呃,确实想不粗来。虽然最近做了好几道DP题,但还是无法保证想得出状态以及状态转移方程。。。不过顺便了解到了DP和贪心的“血缘关系”:如果对于第i个状态,只需第i-1个状态就可以推出第i个状态,对应的推导过程就叫贪心,这种推导过程也是数学上常用的数学归纳法;如果对于第i个状态,仅仅由第i-1个状态无法推出,而需要综合考虑前i-1个状态才能推出,对应的推导过程就叫动态规划,这种方法也叫第二数学归纳法。

    好了,言归正传,我们可以定义状态dp[i][j][k][l]表示这四种卡片的使用数量(状态的得出可以参考数据范围的提示:只有四种卡牌,每种数量不超过40),那么dp[i][j][k][l]=max(dp[i-1][j][k][l],dp[i][j-1][k][l],dp[i][j][k-1][l],dp[i][j][k][l-1])+a[1+i+2*j+3*k+4*l],特别的,dp[0][0][0][0]=a[1],一张都不使用时,棋子处于起点,也有相应分数。具体细节详见代码。

     1 #include<cstdio>
     2 inline int max(int a,int b) {return a>b?a:b;}
     3 const int maxn=355,maxm=125,maxe=45;
     4 int n,m,a[maxn],b,num[5],dp[maxe][maxe][maxe][maxe],ans;
     5 int main() {
     6     scanf("%d%d",&n,&m);
     7     for(int i=1;i<=n;++i) scanf("%d",&a[i]);
     8     for(int i=1;i<=m;++i) {scanf("%d",&b);++num[b];}
     9     dp[0][0][0][0]=a[1];
    10     for(int i=0;i<=num[1];++i)
    11         for(int j=0;j<=num[2];++j)
    12             for(int k=0;k<=num[3];++k)
    13                 for(int l=0;l<=num[4];++l) {
    14                     int to=i+2*j+3*k+4*l+1;
    15                     if(i>0) dp[i][j][k][l]=max(dp[i][j][k][l],dp[i-1][j][k][l]+a[to]);
    16                     if(j>0) dp[i][j][k][l]=max(dp[i][j][k][l],dp[i][j-1][k][l]+a[to]);
    17                     if(k>0) dp[i][j][k][l]=max(dp[i][j][k][l],dp[i][j][k-1][l]+a[to]);
    18                     if(l>0) dp[i][j][k][l]=max(dp[i][j][k][l],dp[i][j][k][l-1]+a[to]);
    19                 }
    20     printf("%d",dp[num[1]][num[2]][num[3]][num[4]]);
    21     return 0;
    22 }
    AC代码
  • 相关阅读:
    19 C#循环语句的跳过和中断 continue和break
    18 C#中的循环执行 for循环
    一种绝对提高开发水平的方法(推荐英语)
    大数据知识普及
    全链路压测压测报告
    QuickSearch快排
    二分查找
    算法
    基于领域驱动设计的业务中台架构设计
    【科普】Scrum——从橄榄球争球到敏捷开发
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9630181.html
Copyright © 2011-2022 走看看