标签:mes span str cst size getc 代码 合并 putc
【题目描述】
众所周知,小葱同学擅长合并,尤其把两个人合并成一个人。但小葱只擅长合并两
个人的情况,当有很多个人之后就会比较苦恼。现在小葱给了你 n 个人排成一个环(即
第一个人和最后一个人相邻),并且每个人左手和右手上各有一个数。每次你可以合并
相邻的两个人,合并这两个人的代价为他们右手的数的差的绝对值,合并之后会变成一
个新的人,新的人左手的数是原来左边的人左手的数,右手的数是原来右边的人右手的
数。现在小葱希望你通过 n − 1 次合并把所有人合并成一个人,并且使得代价最小。求
最小代价。
【输入格式】
从文件 merge.in 中读入数据。
第一行包括 1 个正整数 n。
接下来 n 行每行 2 个正整数代表每个人左手和右手的数。
【输出格式】
输出到文件 merge.out 中。
输出一行一个整数代表最小代价。
【样例 1 输入】
3
1 1
2 2
3 3
【样例 1 输出】
2
【样例 1 解释】
先合并前两个人。
没有心态,模考3道题只有100pts
就是这道区间DP
把环转成链
然后dp[i][j]表示从i到j的最小代价
下面给出代码:
#include<iostream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<cstdio> #include<cstdlib> using namespace std; inline int rd(){ int x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch==‘-‘) f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-‘0‘; return x*f; } inline void write(int x){ if(x<0) putchar(‘-‘),x=-x; if(x>9) write(x/10); putchar(x%10+‘0‘); return ; } int head[100006],tail[100006]; int dp[500][500]; int main(){int n; n=rd(); memset(dp,127,sizeof(dp)); for(int i=1;i<=n;i++){ head[i]=rd(); tail[i]=rd(); head[i+n]=head[i]; tail[i+n]=tail[i]; dp[i][i]=0; dp[i+n][i+n]=0; } for(int l=1;l<n;l++){ for(int i=1;i<=2*n-l;i++){ int j=i+l; for(int k=i;k<j;k++) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+abs(tail[k]-tail[j])); } } int minn=1e9; for(int i=1;i<=n;i++) minn=min(minn,dp[i][i+n-1]); printf("%d",minn); return 0; }
标签:mes span str cst size getc 代码 合并 putc
原文地址:https://www.cnblogs.com/WWHHTT/p/9821428.html