PAT现在不考动态规划了,而且下面的题也不是很难。
1、最大序列和✔
1007 Maximum Subsequence Sum #线性DP
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int n;
cin>>n;
vector<int> v;
int ne_nums=0;
int max_sum=-1,this_sum=0;
int begin=0,this_begin=0;
int end=0;
for(int i=0;i<n;i++){
int x;
cin>>x;
v.push_back(x);
if(x<0) ne_nums+=1;
this_sum+=x;
if(this_sum>max_sum){ //注意(案例5) 中间有一个是0 其他都是负数 (通过零max_sum=-1 解决这个问题)
max_sum=this_sum;
begin=this_begin;
end=i;
}
else if(this_sum<0){
this_sum=0;
if(i!=n-1) this_begin=i+1;
}
}
if(ne_nums==n) cout<<0<<" "<<v[0]<<" "<<v[n-1];
else
cout<<max_sum<<" "<<v[begin]<<" "<<v[end];
}
2、最大颜色序列长度✔
类似背包问题的解法
这个n有个jb用。
y总是按公共子序列那样做的。
1045 Favorite Color Stripe #背包问题
#include<iostream>
#include<vector>
using namespace std;
const int N = 210,M=210,L=10000+10;
int n,m,l;
int love[M];
int order[L];
int f[N][L];
int main(){
cin>>n;
cin>>m;
for(int i=1;i<=m;i++){
cin>>love[i];
}
cin>>l;
for(int i=1;i<=l;i++){
cin>>order[i];
}
int ans=0;
for(int i=1;i<=m;i++){
for(int j=1;j<=l;j++){
if(love[i]==order[j]) f[i][j] = max(f[i-1][j],f[i][j-1])+1;
else f[i][j] = max(f[i-1][j],f[i][j-1]);
// cout<<f[i][j]<<" ";
ans = max(ans,f[i][j]);
}
// cout<<endl;
}
cout<<ans<<endl;
}
3、硬币目标和👍
转化为背包问题,类似目标和。
然后根据题目要求的输出进行处理。
1068 Find More Coins #背包问题
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 10000+10,M=110;
int n,m;
int coins[N];
bool f[N][M];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>coins[i];
}
sort(coins+1,coins+n+1,greater<int>() );
for(int i=0;i<=n;i++) f[i][0]=true;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
f[i][j]=f[i-1][j];
if(j>=coins[i]){
f[i][j]= ( f[i][j] || f[i-1][j-coins[i]]);
}
}
}
vector<int> ans;
int i=1;
for(;i<=n;i++){
if(f[i][m]==1) break;
}
if(i==n+1) {cout<<"No Solution"<<endl;return 0;}
int j=m;
i=n;
while(j!=0){
if(f[i-1][j-coins[i]]==true) {
ans.push_back(coins[i]);
j-=coins[i];
i-=1;
}
else {
i--;
}
}
cout<<ans[0];
for(int i=1;i<ans.size();i++) cout<<" "<<ans[i];
cout<<endl;
}
4、字串PAT的计数✔
结果很大要记得long long
可以在中途不断mod
1093 Count PAT’s #背包问题 #状态机
#include<iostream>
#include<cstring>
using namespace std;
const int N = 100000+10;
long long f[4][N];
int main(){
string task;
cin>>task;
//子序列
for(int j=0;j<task.size();j++) {
f[1][j+1]=f[1][j];
if(task[j]=='P') f[1][j+1]++;
}
for(int j=0;j<task.size();j++){
f[2][j+1]=f[2][j];
if(task[j]=='A') f[2][j+1] += f[1][j+1];
}
for(int j=0;j<task.size();j++){
f[3][j+1]=f[3][j];
if(task[j]=='T') f[3][j+1] += f[2][j+1];
}
cout<< f[3][task.size()] % 1000000007 <<endl;
}
5、一轮快排后的枢纽✔
左边、右边分别遍历两次,遍历中记录最大值和最小值,用于判断非法。
有一个0个枢纽的恶心测试,题目不说明情况。
开始思路错了,是最终位置的不一定是枢纽。4 193 187 23 183 48 72 11 123 164 148 155 160 146 168 27 77 188 9 199
1101 Quick Sort #线性DP
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 100000+10;
int n;
int a[N];
bool iswrong[N];
int main(){
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
int max=0;
for(int i=0;i<n;i++){
if(a[i]<max) iswrong[i]=1;
else{
max=a[i];
}
}
int min=max;
for(int i=n-1;i>=0;i--){
if(a[i]>min) iswrong[i]=1;
else{
min=a[i];
}
}
vector<int> ans;
for(int i=0;i<n;i++) {
if(iswrong[i]==0) ans.push_back(a[i]);
}
sort(ans.begin(),ans.end());
cout<<ans.size()<<endl;
if(ans.size()!=0) cout<<ans[0];
for(auto i=1;i<ans.size();i++) cout<<" "<<ans[i];
cout<<endl;
}