zoukankan      html  css  js  c++  java
  • Acdream1201 SuSu's Power

    题目:SuSu's Power

    链接:http://acdream.info/problem?pid=1201

    题意:一个人站在x轴原点上,初始方向向x轴正方向,由一个字符串来控制其运动,字符串由A、B组成,A表示前进一步,B表示反向,给出字符串,问修改m次字符的情况下,人离原点最远多少?(可以重复修改一个字符,可令 A变B 或 B变A)

    思路:

      最近区间DP做多了,试了好久的区间DP。。。后来发现根本不需要用它(用了时间复杂度太高了。),因为必须把字符串完整用完,所以从第一个字符开始递推就可以了。后来改了方法,又因为不知道m次可以针对同一个字符,错了好多次(思路也基本固定了,后来按原来思路稍加修改居然闯下来了)。。。

      首先,我假定m次必须用完(。。。强装我是故意的),用dp[105][55][2][2]计算,第一维表示下标,第二维表示修改次数,第三维表示方向(向右/向左),第四维表示最大或最小,dp[i][j][0][0]就表示解决前i 个字符,修改j次,当前方向是0的最大值(不是距离)。

      现在递推式就很简单了,按正常逻辑写就可以了,最终M次的答案就是dp[n-1][m][0][0], 01, 10, 11四个的绝对值求最大,必须都考虑,不能认为方向0的最大值一定是正数,举个例子BAB 0。

      最后解决m次可以改变同一字符的情况,假如我改了第一个字符两次,就相当于m=m-2,所以取他们的较大值即可。

    AC代码:

      1 #include<stdio.h>
      2 #include<algorithm>
      3 using namespace std;
      4 #define N 105
      5 #define M 55
      6 #define INF 1e9
      7 /*
      8   dp[i][j][k][x]:
      9   i前,修改j次,当前是加/减,最大值/最小值
     10 */
     11 int dp[N][M][2][2];
     12 void initdp()
     13 {
     14   for(int i=0; i<N; i++){
     15     for(int j=0; j<M; j++){
     16       for(int k=0; k<2; k++){
     17         for(int u=0; u<2; u++){
     18           dp[i][j][k][u]=-INF;
     19         }
     20       }
     21     }
     22   }
     23 }
     24 int add(int x, int y){
     25   if(x==-INF) return -INF;
     26   return x+y;
     27 }
     28 int min(int x, int y)
     29 {
     30   if(x==-INF && y==-INF) return -INF;
     31   else if(x==-INF) return y;
     32   else if(y==-INF) return x;
     33   else return x<y?x:y;
     34 }
     35 int main()
     36 {
     37   int n, m, cas=1;
     38   char s[N];
     39   while(~scanf("%d", &n)){
     40     scanf("%s%d", s, &m);
     41     initdp();
     42     if(s[0]=='A'){
     43       dp[0][0][0][0]=1;
     44       dp[0][0][0][1]=1;
     45       dp[0][1][1][0]=0;
     46       dp[0][1][1][1]=0;
     47     }
     48     else{
     49       dp[0][0][1][0]=0;
     50       dp[0][0][1][1]=0;
     51       dp[0][1][0][0]=1;
     52       dp[0][1][0][1]=1;
     53     }
     54     for(int i=1; i<n; i++){
     55       if(s[i]=='A'){
     56         dp[i][0][0][0]=add(dp[i-1][0][0][0],1);
     57         dp[i][0][0][1]=add(dp[i-1][0][0][1],1);
     58         dp[i][0][1][0]=add(dp[i-1][0][1][0],-1);
     59         dp[i][0][1][1]=add(dp[i-1][0][1][1],-1);
     60         for(int k=1; k<=m && k<=i+1; k++){
     61           dp[i][k][0][0]=max(add(dp[i-1][k][0][0], 1), dp[i-1][k-1][1][0]);
     62           dp[i][k][0][1]=min(add(dp[i-1][k][0][1], 1), dp[i-1][k-1][1][1]);
     63           dp[i][k][1][0]=max(add(dp[i-1][k][1][0], -1), dp[i-1][k-1][0][0]);
     64           dp[i][k][1][1]=min(add(dp[i-1][k][1][1], -1), dp[i-1][k-1][0][1]);
     65         }
     66       }
     67       else
     68       {
     69         dp[i][0][0][0]=dp[i-1][0][1][0];
     70         dp[i][0][0][1]=dp[i-1][0][1][1];
     71         dp[i][0][1][0]=dp[i-1][0][0][0];
     72         dp[i][0][1][1]=dp[i-1][0][0][1];
     73         for(int k=1; k<=m && k<=i+1; k++){
     74           dp[i][k][0][0]=max(add(dp[i-1][k-1][0][0], 1), dp[i-1][k][1][0]);
     75           dp[i][k][0][1]=min(add(dp[i-1][k-1][0][1], 1), dp[i-1][k][1][1]);
     76           dp[i][k][1][0]=max(add(dp[i-1][k-1][1][0], -1), dp[i-1][k][0][0]);
     77           dp[i][k][1][1]=min(add(dp[i-1][k-1][1][1], -1), dp[i-1][k][0][1]);
     78         }
     79       }
     80     }
     81 
     82     //int x, y, z, k;
     83     //while(~scanf("%d%d%d%d", &x, &y, &z, &k)){
     84     //  printf("==> %d
    ", dp[x][y][z][k]);
     85     //}
     86 
     87     int ans=-INF;
     88     while(m>=0)
     89     {
     90       int tmp=-INF;
     91       if(dp[n-1][m][1][1]!=-INF && dp[n-1][m][0][0]!=-INF)
     92         tmp=max(abs(dp[n-1][m][0][0]), abs(dp[n-1][m][1][1]));
     93       else if(dp[n-1][m][0][0]!=-INF) tmp=abs(dp[n-1][m][0][0]);
     94       else if(dp[n-1][m][1][1]!=-INF) tmp=abs(dp[n-1][m][1][1]);
     95 
     96       if(dp[n-1][m][1][0]!=-INF && dp[n-1][m][0][1]!=-INF) tmp = max(tmp, max(abs(dp[n-1][m][0][1]), abs(dp[n-1][m][1][0])));
     97       else if(dp[n-1][m][1][0]!=-INF) tmp=max(tmp, abs(dp[n-1][m][1][0]));
     98       else if(dp[n-1][m][0][1]!=-INF) tmp=max(tmp, abs(dp[n-1][m][0][1]));
     99 
    100       ans=max(ans, tmp);
    101       m-=2;
    102     }
    103 
    104     printf("Case #%d: %d
    ", cas++, ans);
    105   }
    106   return 0;
    107 }
  • 相关阅读:
    【CF536D】Tavas in Kansas(博弈+动态规划)
    【CF643F】Bears and Juice(信息与可区分情况数)
    【AT3981】[ARC093D] Dark Horse(容斥+状压DP)
    【CF708E】Student's Camp(动态规划)
    【洛谷6775】[NOI2020] 制作菜品(思维好题)
    【洛谷2282】[HNOI2003] 历史年份(线段树优化DP)
    【洛谷5068】[Ynoi2015] 我回来了(线段树)
    【洛谷4117】[Ynoi2018] 五彩斑斓的世界(第二分块)
    【洛谷3745】[六省联考2017] 期末考试(水题)
    【AtCoder】AtCoder Grand Contest 050 解题报告(A~D)
  • 原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/6594805.html
Copyright © 2011-2022 走看看