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代码
  • 相关阅读:
    docker 删除所有的 docker ps -a 记录
    使用ES6的Promise完美解决回调地狱
    linux查看历史命令history
    linux命令补全 忘记命令只记得开头
    linux更改shell
    java信号量PV操作 解决生产者-消费者问题
    eclipse代码自动提示功能设置
    linux下mysql修改数据库账户root密码
    IntelliJ Idea12 破解码与中文乱码配置
    linux usermod修改用户所在组方法
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9630181.html
Copyright © 2011-2022 走看看