一.先整理一下做的题
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的课件,军训期间再找点时间补回来。在做题时,有时思路是对的,但代码却实现不了,有时候直接没思路一脸懵逼,有时候还是要考虑的细一点的,还是那句话,要多刷题呀,刷的
题还是少,多做题,多学思路,加油!