中山市第九屆小學生資訊學邀請賽試題 5.合併線段
【題目描述】
有一條很長的尺子,上面標記著整數點的座標。如: 現在給出n條線段,每條線段表示為x—y(x和y為整數,x<=y),兩條線段能合併的條件是x—y,y—z,合併為x—z。比如線段2—4和線段4—6可以合併為線段2—6。(線段2—4和線段3—6則不可以合併為線段2—6) 求最終能合併的最長的線段,且輸出這條最長的線段是由多少條小線段組成的。 比如有6條線段:2—7,1—3,3—12,12—20,7—10,4—50 那麼可以合併成以下線段: 1—3,3—12,12—20 長度為20-1=19 由3個線段組成 2—7,7—10 長度為10-2=8 由2個線段組成 4—50 長度為50-4=46 由1個線段組成 那麼最長的一條就是第三個,所以結果為46,1。 需要注意的是:如果有兩條不一樣的連續的線段長度同時為最大,那麼取組成線段數多的一條。 例子:1—5,5—10,1—10,輸出: 9,2
【輸入檔案】
第一行為一個整數n; 第二行到第n+1行,每行兩個整數A B,記錄一條線段的資訊。
【輸出檔案】
輸出一個整數,即能合併成的最長的線段的長度和組成它的線段數。
【輸入輸出樣例1】
e.in e.out 7 1 5 10 12 3 10 2 7 2 10 12 16 7 9 14 3
【樣例1資料提示】
1—5 長度為4 由1個頁段組成 3—10,10—12,12—16 長度為13 由3個頁段組成 2—7,7—9 長度為7 由2個頁段組成 2—10,10—12,12—16 長度為14 由3個頁段組成 所以輸出最長的頁段的長度即14由3個頁段組成
【資料規模】
對於30%的資料:1<=n<=20;對於100%的資料:1<=n<=500 ,0<=A<B<500
其實這道題有點DP的意思了
先進行排序,y來排序。
我們先定義一個s陣列,s[i]表示以線段i結尾的能合併的線段最長為多長 定義c陣列,c[i]表示以線段i結尾的能合併的線段最長的最多要多少條線段
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
int x,y;
}a[510];
bool cmp(node x,node y){return x.y<y.y;}
int n,s[510],c[510];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%d%d",&a[i].x,&a[i].y);//輸入
sort(a+1,a+n+1,cmp);//排序
for(int i=1;i<=n;++i)
{
s[i]=a[i].y-a[i].x;//初始化,s[i]最長為線段i的長度
c[i]=1;//有一條線段,為線段i
for(int j=i-1;j>=1;--j)
if(a[j].y==a[i].x)
//如果線段i的頭部(x)能和線段j的尾部(y)連線的話
{
if(s[i]<s[j]+a[i].y-a[i].x)//判斷是否能更新長度
{
//能更新
s[i]=s[j]+a[i].y-a[i].x;
c[i]=c[j]+1;//更新長度
}
//若不能更新長度
else if(s[i]==s[j]+a[i].y-a[i].x)
//判斷是否長度相等
{
if(c[i]<c[j]+1)c[i]=c[j]+1;
//可以就更新
}
}
}
int maxa=0,maxb=0;
//maxa求最長的長度,maxb求合併的線段最長的最多要多少條線段
for(int i=1;i<=n;++i)//更新,不多說
{
if(s[i]>maxa)
{
maxa=s[i];maxb=c[i];
}
else if(s[i]==maxa)
{
if(maxb<c[i])maxb=c[i];
}
}
printf("%d %d\n",maxa,maxb);//輸出,完結撒花
return 0;
}
純程式碼
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
int x,y;
}a[510];
bool cmp(node x,node y){return x.y<y.y;}
int n,s[510],c[510];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%d%d",&a[i].x,&a[i].y);
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;++i)
{
s[i]=a[i].y-a[i].x;
c[i]=1;
for(int j=i-1;j>=1;--j)
if(a[j].y==a[i].x)
{
if(s[i]<s[j]+a[i].y-a[i].x)
{
s[i]=s[j]+a[i].y-a[i].x;
c[i]=c[j]+1;
}
else if(s[i]==s[j]+a[i].y-a[i].x)
{
if(c[i]<c[j]+1)c[i]=c[j]+1;
}
}
}
int maxa=0,maxb=0;
for(int i=1;i<=n;++i)
{
if(s[i]>maxa)
{
maxa=s[i];maxb=c[i];
}
else if(s[i]==maxa)
{
if(maxb<c[i])maxb=c[i];
}
}
printf("%d %d\n",maxa,maxb);
return 0;
}