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 }
  • 相关阅读:
    Largest Rectangle in Histogram
    Valid Sudoku
    Set Matrix Zeroes
    Unique Paths
    Binary Tree Level Order Traversal II
    Binary Tree Level Order Traversal
    Path Sum II
    Path Sum
    Validate Binary Search Tree
    新手程序员 e
  • 原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/6594805.html
Copyright © 2011-2022 走看看