2022/4/3 DP专场总结
作者:互联网
虽然现在是清明节假期期间,但架不住竞赛集训啊……
懒得一道一道贴了,所以:比赛链接
A.饭卡
-
一道极其浅显易懂易做的线性DP;
-
虽然但是,还是由于没有取 \(|\) 而吃了两发罚时;
AC code
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define re register
inline int read(){
int s=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)){
s=s*10+int(ch-'0');
ch=getchar();
}
return s*f;
}
const int x=1000;
int n,m;
int p[1005];
int f[2005];
int main(){
while(n=read()){
if(!n) return 0;
for(re int i=1;i<=n;++i)
p[i]=read();
sort(p+1,p+n+1);
m=read();
memset(f,0,sizeof(f));
f[m+x]=1;
int ans=m;
for(re int i=1;i<=n;++i){
for(re int j=5;j<=m;++j){
f[j-p[i]+x]=f[j-p[i]+x]|(1&f[j+x]);
}
}
for(re int i=x-p[n];i<=m+x;++i){
if(f[i]){
ans=i-x;
break;
}
}
printf("%d\n",ans);
}
return 0;
}
B.Cheapest Palindrome
-
是一道同样浅显易懂的区间DP;
-
然而考场上并没有做;
-
考虑枚举区间两个端点 \(s_{st},s_e\) 的状态:
- 如果 \(s_{st}=s_e\),说明是对称的,则不需要修改,有 \(f_{st,e}=min(f_{st,e},f_{st+1,e-1})\);
- 其他的可能:\(f_{st,e}=min(f_{st+1,e}+price_{st},f_{st,e-1}+price_e)\),即分别修改 \(st\) 或 \(e\) 时的最小花费;
-
可以证明,删除和插入效果是等价的,因此 \(price_i\) 取两个花费中的最小值即可;
AC code
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<ios>
using namespace std;
int n,m;
string s;
int v[30][3];
int p[30];
int f[3005][3005];
int main(){
cin>>n>>m;
cin>>s;
char ch;
for(int i=1;i<=n;++i){
cin>>ch;
cin>>v[int(ch-'a')][0]>>v[int(ch-'a')][1];
}
for(int i=0;i<=26;++i)
p[i]=min(v[i][0],v[i][1]);
memset(f,0x3f,sizeof(f));
for(int i=0;i<=s.size();++i)
for(int j=i;j>-1;--j)
f[i][j]=0;
for(int l=1;l<=s.size();++l){
for(int st=1;st+l<=s.size();++st){
int e=st+l;
if(st && s[st-1]==s[e-1])
f[st][e]=min(f[st][e],f[st+1][e-1]);
f[st][e]=min(f[st][e],f[st+1][e]+p[int(s[st-1]-'a')]);
f[st][e]=min(f[st][e],f[st][e-1]+p[int(s[e-1]-'a')]);
// printf("%d %d %d\n",st,e,f[st][e]);
}
}
cout<<f[1][s.size()];
return 0;
}
标签:专场,ch,int,cin,st,2022,include,DP,getchar 来源: https://www.cnblogs.com/Star-LIcsAy/p/16097192.html