1.Uva1625颜色的长度
dp[i][j]表示前一个串选到第i个 后一个串选到第j个 的最小价值
记一下还有多少个没有结束即dp2
记一下每个数开始和结束的位置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; char s1[5100],s2[5100]; int fp[30],fq[30],ep[30],eq[30]; const int INF=2147483233; int dp1[2][5100],dp2[2][5100]; int main() { //freopen("color.in","r",stdin); //freopen("color.out","w",stdout); //写了个意义不明的滚动数组。。。 //BGM:Hop scanf("%s%s",s1+1,s2+1); int n=strlen(s1+1),m=strlen(s2+1); for(int i=1;i<=n;i++)s1[i]-='A'; for(int i=1;i<=m;i++)s2[i]-='A'; for(int i=0;i<26;i++)fp[i]=fq[i]=INF; for(int i=1;i<=n;i++) { fp[s1[i]]=min(fp[s1[i]],i); ep[s1[i]]=i; } for(int i=1;i<=m;i++) { fq[s2[i]]=min(fq[s2[i]],i); eq[s2[i]]=i; } int cur=0; for(int i=0;i<=n+1;i++) { for(int j=0;j<=m+1;j++) { if(!i && !j)continue; int v1=INF,v2=INF; if(i)v1=dp1[cur^1][j]+dp2[cur^1][j]; if(j)v2=dp1[cur][j-1]+dp2[cur][j-1]; dp1[cur][j]=min(v1,v2); if(i) { dp2[cur][j]=dp2[cur^1][j]; if(fp[s1[i]]==i&&fq[s1[i]]>j)dp2[cur][j]++; if(ep[s1[i]]==i&&eq[s1[i]]<=j)dp2[cur][j]--; } else if(j) { dp2[cur][j]=dp2[cur][j-1]; if(fq[s2[j]]==j&&fp[s2[j]]>i)dp2[cur][j]++; if(eq[s2[j]]==j&&ep[s2[j]]<=i)dp2[cur][j]--; } } cur=cur^1; } cout<<dp1[cur^1][m]; return 0; }
2.Uva12563劲歌金曲
首先留出1s来唱最后一首歌
剩下的简单的背包+记录路径
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int MAXN=110000; int n,T; int a[MAXN]; int w[55]; int b[MAXN]; int main() { freopen("party.in","r",stdin); freopen("party.out","w",stdout); cin>>n>>T; for(int i=0;i<n;i++)cin>>w[i]; T=min(T,100010); T--;//长者续命-1s 苟利国家生死以岂因祸福避趋之 敢同恶鬼争高下,不向霸王让寸分 //你们啊Naive!你们有一个好 全世界到哪个地方你们比其他的西方记者跑的还快 //美国的华莱士不知比你们高到哪里去了我跟他谈笑风生 sort(w,w+n); for(int i=0;i<n;i++) for(int j=T;j>=w[i];j--) if((b[j]<b[a[j-w[i]]]+1) || (b[j]==b[a[j-w[i]]]+1 && a[j]<a[j-w[i]]+w[i]) ) { a[j]=a[j-w[i]]+w[i]; b[j]=b[a[j-w[i]]]+1; } b[T]++; cout<<b[T]<<" "<<a[T]+678; return 0; }
3.回文子串
把一个字符串切成若干回文子串 问最少切多少个
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int MAXN=1010; const int INF=2147483233; int dp[MAXN]; char s[MAXN]; bool judge(int i,int j) { while(i<j)if(s[i++]!=s[j--])return false; return true; } int main() { freopen("string.in","r",stdin); freopen("string.out","w",stdout); scanf("%s",s+1); dp[0]=0; int len=strlen(s+1); for(int i=1;i<=len;i++)dp[i]=INF; for(int i=1;i<=len;i++) for(int j=1;j<=i;j++) if(judge(j,i))dp[i]=min(dp[i],dp[j-1]+1); printf("%d ",dp[len]); return 0; }
4.切木棍
有一个长为L的棍子,还有n个切割点的位置(按从小到大排列)。你的任务是在这些切割点的位置处把棍子切成n+1部分,使得总切割的费用最少。每次切割的费用等于被切割的木棍长度。
区间dp
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; int l,n; const int inf=2147483233; int dp[150][150]; int a[150]; int main() { freopen("stick.in","r",stdin); freopen("stick.out","w",stdout); scanf("%d%d",&l,&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]);a[0]=0;a[n+1]=l; sort(a+1,a+n+1); for(int len=2;len<=n+1;len++) for(int i=0;i<=n+1-len;i++) { dp[len][i]=inf; for(int j=1;j<=len-1;j++)dp[len][i]=min(dp[len][i],dp[j][i]+dp[len-j][i+j]+a[len+i]-a[i]); } cout<<dp[n+1][0]; }
5.走过去再走回来
给定平面上n个点(横坐标严格递增)你要从最左边走到最右边再走回来 走欧几里得距离 而且要求每个点都走到 求走的最短路
一开始到洗手间数学证明了半天。。。后来发现还是鸡神设计的状态好(Orz Jackyyc)
dp[i][j]表示前面的人走到i 后面的人走到j 且1~i每个点都走过了
然后记忆化搜索嗖嗖嗖就出来了
再次Orz Jackyyc
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> using namespace std; inline int read() { char ch=getchar(); int x=0,f=1; while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();} while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();} return x*f; } const double eps=1e-4; struct point { double x,y; }p[1010]; double d(point a,point b) { double ans=sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); return ans; } int n; double dp[1010][1010]; double dis[1010][1010]; double Dp(int a,int b) { if(dp[a][b])return dp[a][b]; else return dp[a][b]=min(Dp(a+1,b)+dis[a][a+1],Dp(a+1,a)+dis[b][a+1]); } int ans=2147483647.0; int main() { freopen("route.in","r",stdin); freopen("route.out","w",stdout); n=read(); for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y); for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)dis[i][j]=d(p[i],p[j]); for(int i=1;i<n-1;i++)dp[n-1][i]=dis[n-1][n]+dis[i][n]; double ans=Dp(1,1); printf("%.2lf",ans); return 0; }
6.城市里的间谍uva1025
预处理比较烦
judge[t][i][0]表示在时间t 车站i 有一个向左开的车
judge[t][i][1]表示在时间t 车站i 有一个向右开的车
对于每个时间 有三个决策 不动 朝左 朝右
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; inline int read() { char ch=getchar(); int x=0,f=1; while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();} while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();} return x*f; } const int INF=2147483233; int n,m,T,M; const int maxn=300; int t[maxn],d[maxn],D[maxn]; bool judge[maxn][maxn][2]; int dp[maxn][maxn]; int main() { freopen("spy.in","r",stdin); freopen("spy.out","w",stdout); scanf("%d%d",&n,&T); for(int i=1;i<=n-1;i++)scanf("%d",&t[i]); scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d",&d[i]); int te=d[i]; if(d[i]<T)judge[d[i]][1][1]=1; for(int j=1;j<=n-1;j++) { if(te+t[j]<=T) { judge[te+t[j]][j+1][1]=1; te=te+t[j]; } else break; } } scanf("%d",&M); for(int i=1;i<=M;i++) { scanf("%d",&D[i]); int te=D[i]; if(D[i]<T)judge[D[i]][n][0]=1; for(int j=n-1;j>=1;j--) { if(te+t[j]<=T) { judge[te+t[j]][j][0]=1; te=te+t[j]; } else break; } } for(int i=1;i<=n-1;i++)dp[T][i]=INF; dp[T][0]=0; for(int i=T-1;i>=0;i--) { for(int j=1;j<=n;j++) { dp[i][j]=dp[i+1][j]+1; if(j<n && judge[i][j][1] && i+t[j]<=T)dp[i][j]=min(dp[i][j],dp[i+t[j]][j+1]); if(j>1 && judge[i][j][0] && i+t[j-1]<=T)dp[i][j]=min(dp[i][j],dp[i+t[j-1]][j-1]); } } if(dp[0][1]>=INF)cout<<"impossible"; else cout<<dp[0][1]; }