zoukankan      html  css  js  c++  java
  • 【纪中受难记】——Day4:失去梦想的咸鱼

    世界上没有什么困难能阻挡我前进,除非是调试一个水题调了半个小时……

    0/40(60?)/0


    Description

    小X 看到堆成山的数列作业十分头疼,希望聪明的你来帮帮他。考虑数列A=[A1,A2,...,An],定义变换f(A,k)=[A2,A3,,,,.Ak,A1,Ak+2,Ak+3,,,,A2k,Ak+1,...],也就是把a 分段,每段k 个(最后如果不足k 个,全部分到新的一段里,见样例),然后将每段的第一个移动到该段的最后一个。

    现在,小 X想知道 f (f (f (f ([1,2,3,⋯,n],2),3),⋯),n)的结果。
     

    Input

    输入一行包含一个整数n 。

    Output

    输出一行包含n 个整数,表示最终的数列。
     

    Sample Input

    4

    Sample Output

    4 2 3 1

    【样例说明】
    f ([1,2,3,4],2) = [2,1,4,3]
    f ([2,1,4,3],3) = [1,4,2,3](3单独被分在一组,移动到组的最后一位,仍然是3)
    f ([1,4,2,3],4) = [4,2,3,1]
     

    Data Constraint

    对于60%的数据,1≤ n ≤10^3。

    对于100%的数据,1≤ n ≤10^6。

    这道题在听到一位神仙说出解法前,还以为正解是dp……

    解法就是将数组不断右移,然后把跳到尾端的移到下一个即将跳到尾端的数字上去。

    eg:1 2 3

    k=2:1  2  1 4 3

    k=3:1  2 1 4 2  3

    注意到最后一个区间跳跃的数,它应该预判一下n%k是否等于0,如果整除就不用管(我被坑了好久)。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 const int N=1e6+10;
     5 int n;
     6 int b[N*2];
     7 int main(){
     8     scanf("%d",&n);
     9     for(int i=1;i<=n;i++){
    10         b[i]=i;
    11     } 
    12     for(int k=2;k<=n;k++){
    13         int tail=n-n%k+k-1,re=b[tail];
    14         for(int i=tail;i>=k-1;i-=k){
    15             b[i]=b[i-k];
    16         }
    17         if(n%k!=0)
    18         b[n+k-1]=re;
    19     }
    20     for(int i=n;i<=2*n-1;i++)
    21     printf("%d ",b[i]);
    22     return 0;
    23 }

    Description

    小X 为了展示自己高超的游戏技巧,在某一天兴致勃勃地找小Y 玩起了一种卡牌游戏。每张卡牌有类型(攻击或防御)和力量值两个信息。

    小Y 有n 张卡牌,小X 有m 张卡牌。已知小X 的卡牌全是攻击型的。

    游戏的每一轮都由小X 进行操作,首先从自己手上选择一张没有使用过的卡牌X。如果小Y 手上没有卡牌,受到的伤害为X 的力量值,否则小X 要从小Y 的手上选择一张卡牌Y。若Y 是攻击型(当X 的力量值不小于Y 的力量值时才可选择),此轮结束后Y 消失,小Y 受到的伤害为X 的力量值与Y 的力量值的差;若Y 是防御型(当X 的力量值大于Y 的力量值时才可选择),此轮结束后Y 消失,小Y 不受到伤害。

    小X 可以随时结束自己的操作(卡牌不一定要用完)。希望聪明的你帮助他进行操作,使得小Y 受到的总伤害最大。
     

    Input

    输入的第一行包含两个整数n 和m 。

    接下来n 行每行包含一个字符串和一个整数,分别表示小Y 的一张卡牌的类型(“ATK”表示攻击型,“DEF”表示防御型)和力量值。

    接下来m 行每行包含一个整数,表示小X 的一张卡牌的力量值。

    Output

    输出一行包含一个整数,表示小Y 受到的最大总伤害。
     

    Sample Input

    输入1:
    2 3
    ATK 2000
    DEF 1700
    2500
    2500
    2500

    输入2:
    3 4
    ATK 10
    ATK 100
    ATK 1000
    1
    11
    101
    1001
     

    Sample Output

    输出1:
    3000
    【样例说明1】
    第一轮,小X 选择自己的第一张卡牌和小Y 的第二张卡牌,小Y 的第二张卡牌消失。
    第二轮,小X 选择自己的第二张卡牌和小Y 的第一张卡牌,小Y 的第一张卡牌消失,同时受到500 点伤害。
    第三轮,小X 选择自己的第三张卡牌,此时小Y 手上已经没有卡牌,受到2500 点伤害。
    小X 结束游戏,小Y 共受到3000点伤害。

    输出2:
    992
    【样例说明2】
    第一轮,小X 选择自己的第三张卡牌和小Y 的第一张卡牌,小Y 的第一张卡牌消失,同时受到91点伤害。
    第二轮,小X 选择自己的第四张卡牌和小Y 的第二张卡牌,小Y 的第二张卡牌消失,同时受到901点伤害。
    小X 结束游戏,小Y 共受到992点伤害。
     
     

    Data Constraint

    各规模均有一半数据满足小Y 只有攻击型卡牌。

    对于30%的数据,1≤ n,m ≤ 6。

    对于60%的数据,1≤ n,m ≤10^3。

    对于100%的数据,1≤ n,m ≤10^5,力量值均为不超过10^6的非负整数。

    这道题是贪心。

    考虑几种情况:

    1.只消耗对方攻击牌:

      我们用最大的攻击牌攻击对方最小的攻击牌,然后拿次大的攻击次小的,证明如下:

      如果存在一个牌x<对方某一攻击牌y,我方共用牌点为X,对方为Y,则我方得分为X-Y,但是可知x-y<0 所以再攻击也不会得到更多优势,故不去攻击。

    2.消耗对方所有牌再造成直接伤害:

        如果消耗所有牌的话,应当先攻击防御牌,用等大或者稍大的牌消掉防御牌再去攻击其他的,假设能消耗所有攻击牌,则得分为:sum[x]-def[x]-atk[y](sum是我方牌总分数,def是用在攻击防御牌上的总分数,atk是敌方攻击牌总分数)

    以上两种情况取最大即可。

    不知道为啥只有80分。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 typedef long long ll;
     7 const ll N=1e5+10;
     8 ll n,m,ans,maxans;
     9 ll atk[N],dfn[N],ca,cb,vis[N],flag1,flag2;
    10 ll x[N];
    11 int main(){
    12     freopen("card17.in","r",stdin);
    13     scanf("%lld%lld",&n,&m);
    14     char a[10];
    15     ca=cb=0;
    16     for(ll i=1,k;i<=n;i++){
    17         cin>>a;
    18         scanf("%lld",&k);
    19         if(a[0]=='A') atk[++ca]=k;
    20         else dfn[++cb]=k;
    21     }    
    22     sort(atk+1,atk+ca+1);
    23     sort(dfn+1,dfn+cb+1);
    24     for(ll i=1;i<=m;i++) scanf("%lld",&x[i]);
    25     sort(x+1,x+m+1);
    26     ll ans=0;
    27     ll i,j;
    28     for(i=1,j=1;i<=ca&&j<=m;){
    29         while((x[j]<atk[i]&&j<=m)||vis[j]) j++;
    30         if(j>m) break;
    31         ans+=x[j]-atk[i];
    32         vis[j]=1;
    33         i++;
    34     }
    35     if(i>ca) flag1=1;
    36     for(i=1,j=1;i<=cb&&j<=m;){
    37         while((x[j]<dfn[i]&&j<=m)||vis[j]) j++;
    38         if(j>m) break;
    39         vis[j]=1,i++;
    40     }
    41     if(i>cb) flag2=1;
    42     if(flag1&flag2) for(i=1;i<=m;i++) if(!vis[i]) ans+=x[i];
    43     maxans=max(ans,maxans);
    44     memset(vis,0,sizeof(vis));
    45     flag1=flag2=ans=0;
    46     for(i=1,j=1;i<=cb&&j<=m;){
    47         while((x[j]<dfn[i]&&j<=m)||vis[j]) j++;
    48         if(j>m) break;
    49         vis[j]=1,i++;
    50     }
    51     if(i>cb) flag2=1;
    52     for(i=1,j=1;i<=ca&&j<=m;){
    53         while((x[j]<atk[i]&&j<=m)||vis[j]) j++;
    54         if(j>m) break;
    55         ans+=x[j]-atk[i];
    56         vis[j]=1;
    57         i++;
    58     }
    59     if(i>ca) flag1=1;
    60     if(flag1&flag2) for(i=1;i<=m;i++) if(!vis[i]) ans+=x[i];
    61     maxans=max(maxans,ans);
    62     memset(vis,0,sizeof(vis));
    63     flag1=flag2=ans=0;
    64     ll pt[N];
    65     for(ll i=m,j=1;i>=1&&j<=ca;){
    66         if(x[i]>atk[j]) ans+=x[i]-atk[j],vis[i]=1,i--,j++;
    67         else break;
    68     }
    69     ll t=0;
    70     for(ll i=1;i<=m;i++) if(vis[i]) t++; 
    71     if(t==ca) flag1=1;
    72     for(i=1,j=1;i<=cb&&j<=m;){
    73         while((x[j]<dfn[i]&&j<=m)||vis[j]) j++;
    74         if(j>m) break;
    75         vis[j]=1,i++;
    76     }
    77     if(i>cb) flag2=1;
    78     if(flag1&flag2) for(i=1;i<=m;i++) if(!vis[i]) ans+=x[i];
    79     maxans=max(maxans,ans);
    80     printf("%lld",maxans);
    81     return 0;
    82 }

    Description

    小X 终于找到了自己的舞台,希望进行一次尽兴的表演。

    不妨认为舞台是一个n 行m 列的矩阵,矩阵中的某些方格上堆放了一些装饰物,其他的则是空地。小X 可以在空地上滑动,但不能撞上装饰物或滑出舞台,否则表演就失败了。

    小Y 为了让小X 表演得尽量顺畅,提前为小X 写好了每一段时间的移动方向。每个时刻,听话的小X 都会依据小Y 写好的所在时间段的方向(东、西、南、北)向相邻的方格滑动一格。由于小Y 之前没有探查过舞台的情况,如果

    小X 直接按照小Y 写好的来移动,很容易表演失败。

    不过,小Y 是个天使,拥有让小X 停在原地的魔法,也就是某一时刻,小X 以为自己移动了实际上没有移动。为了让小X 表演得尽量完美,小Y 想使小X 在舞台上滑行的路程尽量长(当然不能中途表演失败)。可惜小Y 的智商不足

    以完成这么复杂的计算,希望你来帮助她决定哪些时刻该使用魔法。当然,她关心的首先是最长的路程是多少。
     

    Input

    输入的第一行包含五个整数n,m, x, y 和k 。(x, y )为小 X的初始位置,k 为时间的段数。

    接下来n 行每行包含m 个字符,描述这个舞台(“.”表示该位置是空地,“x”表示该位置有装饰物)。

    接下来k 行每行包含三个整数si ti di (1<= i<= k ),表示在时间段[si,ti ] 内,小 X的移动方向是di 。di 为1,2,3,4中的一个,依次表示北、南、西、东(分别对应矩阵中的上、下、左、右)

    Output

    输出一行包含一个整数,表示小X 滑行的最长路程。
     

    Sample Input

    4 5 4 1 3
    ..xx.
    .....
    ...x.
    .....
    1 3 4
    4 5 1
    6 7 3

    Sample Output

    6
     

    Data Constraint

    保证输入的时间段是连续的,即 s1 =1 ,si=ti-1+1(1<i<=k) ,tk=t。

    对于30%的数据,1≤ t ≤ 20。

    对于60%的数据,1≤t ≤ 200。

    对于100%的数据,1≤ n,m,k ≤ 200,1≤t ≤10^5。

    这题调试要了我老命。

    读题目,这道题并不难设状态,设f[k][i][j]表示在第k次转弯后停在(i,j)时走的最长步数,

    f[k][i][j]=max(f[k-1][x][y]+step),其中(x,y)表示上次停的位置,枚举这个位置,然后更新方向上的step就可以了。

    注意一点,初始状态除了起点以外都为-1。

     1 #include<bits/stdc++.h>
     2 #pragma GCC optimize(3) 
     3 using namespace std;
     4 const int N=210;
     5 const int T=1e5+10;
     6 int n,m,xx,yy,k;
     7 int a[N][N];
     8 int f[N][N][N],ans;
     9 struct Time{
    10     int s,t,d;
    11 }r[N];
    12 int main(){
    13     scanf("%d%d%d%d%d",&n,&m,&xx,&yy,&k);
    14     char q;
    15     for(int i=1;i<=n;i++){
    16         for(int j=1;j<=m;j++){
    17             cin>>q;
    18             a[i][j]=(q=='.'?0:1);
    19         }
    20     }
    21     int s,t,d;
    22     int maxt=0;
    23     for(int i=1;i<=k;i++){
    24         scanf("%d%d%d",&s,&t,&d);
    25         r[i]=(Time){s,t,d};
    26     }
    27     memset(f,-1,sizeof(f));
    28     f[0][xx][yy]=0;
    29     for(int i=1;i<=k;i++){
    30         for(int x=1;x<=n;x++){
    31             for(int y=1;y<=m;y++){
    32                 if(f[i-1][x][y]==-1) continue;
    33                 f[i][x][y]=max(f[i][x][y],f[i-1][x][y]);
    34                 if(r[i].d==1){
    35                     for(int step=1;step<=r[i].t-r[i].s+1;step++){
    36                         if(a[x-step][y]||x-step<=0) break;
    37                         f[i][x-step][y]=max(f[i][x-step][y],f[i-1][x][y]+step);
    38                         if(f[i][x-step][y]>ans) ans=f[i][x-step][y];
    39                     }
    40                 }
    41                 else if(r[i].d==2){
    42                     for(int step=1;step<=r[i].t-r[i].s+1;step++){
    43                         if(a[x+step][y]||x+step>n) break;
    44                         f[i][x+step][y]=max(f[i][x+step][y],f[i-1][x][y]+step);
    45                         if(f[i][x+step][y]>ans) ans=f[i][x+step][y];
    46                     }
    47                 }
    48                 else if(r[i].d==3){
    49                     for(int step=1;step<=r[i].t-r[i].s+1;step++){
    50                         if(a[x][y-step]||y-step<=0) break;
    51                         f[i][x][y-step]=max(f[i][x][y-step],f[i-1][x][y]+step);
    52                         if(f[i][x][y-step]>ans) ans=f[i][x][y-step];
    53                     }
    54                 }
    55                 else{
    56                     for(int step=1;step<=r[i].t-r[i].s+1;step++){
    57                         if(a[x][y+step]||y+step>m) break;
    58                         f[i][x][y+step]=max(f[i][x][y+step],f[i-1][x][y]+step);
    59                         if(f[i][x][y+step]>ans) ans=f[i][x][y+step];
    60                     }
    61                 }
    62             }
    63         }
    64     }
    65     printf("%d",ans);
    66     return 0;
    67 }

    总结:下次要比今天多100分,否则就太菜了。

    ——抓住了时间,却不会利用的人,终究也逃不过失败的命运。
  • 相关阅读:
    落花美眷,终究抵不过逝水流年,回忆我的2016,展望2017。
    如何对于几百行SQL语句进行优化?
    基于.NET Socket API 通信的综合应用
    数据库备份定期删除程序的开发。
    如何开发应用程序将客户服务器数据库的备份,下载到本地的云服务上?
    从大公司做.NET 开发跳槽后来到小公司的做.NET移动端微信开发的个人感慨
    asp.net mvc entity framework 数据库 练习(一)
    ASP.NET CORE小试牛刀:干货(完整源码)
    [开源].NET数据库访问框架Chloe.ORM
    SqlBulkCopy简单封装,让批量插入更方便
  • 原文地址:https://www.cnblogs.com/Nelson992770019/p/11299327.html
Copyright © 2011-2022 走看看