NC15600. 小Y写文章
描述
小Y写了一篇文章,他对自己的文笔很有自信,尤其是自己总结出了一套计算文章通顺性的公式。
文章共N段,对于文章的每一段小Y对它都能计算出一个估值,而一篇文章的不连贯值定义为,现在小Y想要发布他的文章,但是编辑小Z让他加入一些广告,具体来说就是M段估值分别为的新段落。小Y很头疼,想让修改后的文章依然通顺,也就是要最小化不连贯值,已知小Y加入新段落的时候不需要考虑新段落之间的顺序,但是只可以在原文章的开头段之前、结尾段之后、或两段之间加入一段新段落,每个位置只能加入最多一段。请帮助焦头烂额的小Y求出将这M个新段落全都加入之后的最小不连贯值。
输入描述
多组数据,第一行有一个正整数表示数据组数。
之后有T组数据,每组数据第一行有两个整数。
接着有两行,其中第一行有N个正整数,表示原文章按顺序每段的估值。
第二行有M个正整数,表示新段落每段的估值。
输出描述
对于每组数据,输出一个整数表示求出的最小不连贯值。
示例1
输入:
2 4 3 1 6 5 2 3 1 4 4 2 1 2 4 3 10 10
输出:
3 7
说明:
第一组样例方案可以是 (1) 1 (4) 6 5 (3) 2C++11(clang++ 3.9) 解法, 执行用时: 786ms, 内存消耗: 608K, 提交时间: 2018-04-15 15:54:33
#include<bits/stdc++.h> using namespace std; int t,n,m,i,j,l,r,mid,a[205],b[205],d[205][205],c[205]; bool v[205]; int A(int x) { if(x<0)return -x; return x; } bool dfs(int x) { for(int i=1;i<=n;i++)if(!v[i]&&d[x][i]<=mid) { v[i]=1; if(!c[i]||dfs(c[i])) { c[i]=x; return 1; } } return 0; } int main() { scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++)scanf("%d",a+i); for(i=1;i<=m;i++) { scanf("%d",b+i); d[i][1]=A(b[i]-a[1]); for(j=1;j<n;j++)d[i][j+1]=max(A(b[i]-a[j]),A(b[i]-a[j+1])); d[i][n+1]=A(b[i]-a[n]); } for(;i<=n+1;i++) { d[i][1]=0; for(j=1;j<n;j++)d[i][j+1]=A(a[j+1]-a[j]); d[i][n+1]=0; } n++; l=0; r=1000000000; while(l+1<r) { mid=l+r>>1; fill(c+1,c+n+1,0); for(i=1;i<=n;i++) { fill(v+1,v+n+1,0); if(!dfs(i))break; } if(i>n)r=mid; else l=mid; } cout<<r<<endl; } return 0; }