每周总结

142 篇文章 0 订阅
92 篇文章 0 订阅

一.先整理一下做的题

1.dp  How to types

题意:一个人打一串字符包含大小写字母,但他有个习惯最后大写键亮着的话,他一定会关闭,
shift键也可以实现大小写转化。
思路:分成大写键开着(dpb)和不开(dpa)两种情况,最后输出最小值即可,不要忘记dpb最后要关闭
大写键,即dpb+1。

#include <iostream>
#include<string>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int Max=0x7f7f7f7f;//


int main()
{
    int t;
    cin>>t;
    while(t--){
     char s[110],a[110];
     int dpa[110],dpb[110];
     memset(dpa,0,sizeof(dpa));
     memset(dpb,0,sizeof(dpb));
     dpa[0]=0;
     dpb[0]=1;
     
     cin>>a;
     int len=strlen(a);
     for(int i=1;i<=len+1;i++)
     s[i]=a[i-1];
     for(int i=1;i<=len;i++){
         if(s[i]<='z'&&s[i]>='a'){
             dpa[i]=min(dpa[i-1]+1,dpb[i-1]+2);//灯灭就输入字母,灯开就灭灯再输入字母,或按shift再输入字母。要保持和dpa一样的状态
             dpb[i]=min(dpa[i-1]+2,dpb[i-1]+2);//灯灭就输入字母再开灯,灯亮就按shift键再输入字母。要保持和dpb一样的状态
      }
      if(s[i]<='Z'&&s[i]>='A'){
             dpa[i]=min(dpa[i-1]+2,dpb[i-1]+2);//灯灭就按shift键再输入字母,灯亮输入字母再关灯
             dpb[i]=min(dpa[i-1]+2,dpb[i-1]+1);//灯灭就开灯输入字母,灯亮就直接输入字母
      }}
      int min1=min(dpa[len],dpb[len]+1);
      cout<<s[1]<<endl;
      cout<<min1<<endl;}
    return 0;
}

2.坐公交问题

题意:一个人坐公交或电车,一张票在连续(ai=ai+1=...=aj-1=‘A’(‘B’))的情况下可以做多辆车,但他身上钱不一定
   够做全部的车,所以问他最小可以从第几辆开始做
   思路:上面的思路时间借鉴的一个大佬的,她的思路就是顺着来的,在A和B的交界处求出加和,再创一个循环从前开始减去每个
   票的价格,一直到sum<=p,最后输出i和len的最小值即可。

#include<bits/stdc++.h>
using namespace std;
int main(){
   int t;
   cin>>t;
  while(t--){
    int n,a,b,p,j;
    cin>>a>>b>>p;
  long long sum=0;
    string t;
    cin>>t;
    int len=t.size();
    t='*'+t;
    for(int i=1;i<=len;){
        j=i;
        while(j<=len&&t[i]==t[j]) j++;
        sum+=(long long)(t[i]=='A'?a:b);
        i=j;
        if(i==len)
            break;
    }
    int i;
    for(i=1;i<=len;){
        if(sum<=p) break;
        j=i;
        while(j<=len&&t[i]==t[j]) j++;
        sum-=(long long)(t[i]=='A'?a:b);
        i=j;
        if(i==len)
            break;
    }
    cout<<min(i,len)<<endl;
  }
   return 0;
   }


   上面的代码是正着来的,我一开始的思路是反着来的,因为他是问最少可以做到第几站,那从后往前看,一直看到钱不够就行了,我觉得思路挺好的,但是由于代码能力
   有点差,没能实现,卡在了细节上,打完之后看了看同学的,恍然大悟,哇,竟然这么简单,上代码。

#include<iostream>
#include<string>
using namespace std;
int main(){
    int t;
    cin>>t;
    while(t--){
        int a,b,p;
        cin>>a>>b>>p;
        string s;
        cin>>s;
        int len=s.size();
        s='*'+s;//让字符串从1开始计数
        cout<<s[len]<<endl;
        int i;
        s[len]='\0';/*仔细一想,最后一站其实并不重要因为前一站够钱,就可以在前一站做到最后一站,如果不够就走到最后一站
        这与最后一站和前一站是否相等无关。*/
        cout<<s[len]<<endl;
        for( i=len-1;i>=1;i--){
        if(s[i]==s[i+1]){
        continue;}
      else { if(s[i]=='A'){
              if(p>=a) p-=a;
              else break;}
              else{if(p>=b) p-=b;
                  else break;}
                  }
                  }
            
            cout<<i+1<<endl;
          //  cout<<s[0]<<endl;
            }
            return 0;}
            

3.Mashmokh and ACM

题意:n为序列的最大值,k为序列长度,如果ai%ai-1==0,就说这是个好序列,
问最大元素为n,长度为的序列最多有多少个好序列。
思路:dp[i][j],i为序列的长度,j为以j为结尾的序列,整除就说明在结尾j的基础上再加个j成为新的结尾就行了,
这样可以保证求出来的序列是最多的,每个dp[i][j]都只与前一个有关系,所以就考虑与前一个的关系就可以了。

#include <iostream>
#include<string>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int Max=0x7f7f7f7f;//
const int mod=1e9+7;
 int dp[2010][2010];
int main()
{
    int n,k;
    cin>>n>>k;
   dp[0][1]=1;
    for(int i=1;i<=k;i++){
        for(int j=1;j<=n;j++){
            for(int l=j;l<=n;l+=j){
                dp[i][l]=(dp[i][l]+dp[i-1][j])%mod;}
                }
                }
                int ans=0;
                for(int i=1;i<=n;i++)
                ans=(ans+dp[k][i])%mod;
                cout<<ans<<endl;
                return 0;
                }

4.CodeForces - 1321B 旅游景点

题意:有n座城市,每座城市有自己的景点值a[i],小明去了第i座的城市后只能去比i大的城市,而且要满足j-i=a[j]-a[i],求小明能获得的最大的
景点值。
思路:我们可以将等式a[j]-a[i]=j-i转化成a[j]-j=a[i]-i,所以就产生了景点值减去下标这个新变量,然后把所有相等的变量都加起来,看看哪个大输出即可。

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+5;
long long max1=0;
int main(){
    int n,x;
    cin>>n;
map<int,long long>a;//用map不会超数据
    for(int i=1;i<=n;i++){
        cin>>x;
        a[x-i]+=x;
        max1=max(max1,a[x-i]);
    }
    cout<<max1<<endl;
    return 0;
 }

5.奇数和

题意:输入一个数n,看看是否有k个奇数的和等于n,若等于则yes,否则no

思路:看了题解知道的规律。。。
1.前k个奇数的和是k的平方,如果n比k的平方小一定不可能
2.偶数个奇数一定是偶数,奇数个奇数一定是奇数,只要判断n和k的奇偶性即可,因为只要取最小的k个互不相同的奇数,然后把最后一个奇数一直加2直到满足条件即可,
这样k个奇数仍然互不相同。
3.k要long long。

#include<bits/stdc++.h>
using namespace std;

int main(){
int t;
cin>>t;
while(t--){
   int n;long long k;
   cin>>n>>k;
   if(n<k*k){
    cout<<"NO"<<endl;
    continue;
   }
   if((n%2==0&&k*k%2==0)||(n%2!=0&&k*k%2!=0))
    cout<<"YES"<<endl;
   else cout<<"NO"<<endl;
}
return 0;
}

二.收获与感受

收获:对做线性dp的题有了初步的方向,如果设dp[i][j],则就要看他周围的变量是怎么变化的,看看dp[i-1][j],dp[i][j-1]等与dp[i][j]有什么关系 ,然后逐步推出状态方程。

对于cf上的a题或是b题也是能做几道了,一开始一道也做不出来(想想也真是蒟蒻呀)一般都是些思维题,而这些题大致都是些奇技淫巧的题目,可以找出一定的规律,需要对数字有一定的敏感度。

感受:上周由于没有把握好时间导致线性dp的题没有按时完成,正想打开做时发现已经结束了,之后又补做了几道,再加上专业课的原因,区间dp一直没有开始,到现在为止也是欠了一屁股的作业,

今天看了点区间dp的课件,军训期间再找点时间补回来。在做题时,有时思路是对的,但代码却实现不了,有时候直接没思路一脸懵逼,有时候还是要考虑的细一点的,还是那句话,要多刷题呀,刷的

题还是少,多做题,多学思路,加油!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

killer_queen4804

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值