您的位置:首页 > 其它

B - poset

2016-09-20 15:54 120 查看
不想打了。。

分配小组(poset.pas)

[问题描述]

有N个Mars人想要进行一项活动。他们需要分成几个小组,每个人属于其中一个小组。Mars人从出生起每个人就有一个印记,这个印记是个正整数。如果B的印记是A的倍数,那么B就是A的父亲。与地球人的定义不现,一个Mars人可以有多个父亲。特别的,A不是自己的父亲,但是所有其他与A的印记相同的人都是A的父亲。因此,除了A自己,A的父亲的父亲都是A的父亲。

Mars人十分强调子女的独立,因此进行这项活动的分组时,任何人都不能和自己的父亲分到同一个小组。你的任务就是对于给定的Mars人,给出一种分组方案,使得小组的数量最少。显然,这个问题一定存在可行解——你可以让每个Mars人单独一组。如果有多解,任意输出一组即可。

[输入文件]

第一行:一个整数N,表示Mars人的数量。

接下来一行有N个正整数,表示每个Mars人的印记。

[输出文件]

前K行,每行包含若干个整数,每一行的整数表示相应小组的每个人的印记。相邻整数用一个空格分开,每一行的末尾应该保留一个空格。

最后一行是一个整数K,表示你分成的小组数量。

[样例输入]



1 1 3 1 5

[样例输出]

1

1

1

3 5

4

[样例说明]

三个1必须分别分成一组;3和5不是倍数关系,可以分成一组。

[数据规模及约定]

N<=5000

1<=所有印记<=5000
2333
很显然1只有自己在一个集合。

  首先我们排一次序,这样可以避免小数除大数等等诸多不便。

    然后,对于一个数,我们枚举比它小的数。如果一个数不能整除这个数,并且它所在集合的其它数也不能整数这个数,那么就把它加入这个集合。

    如果集合中有一个数能整除,那就没得谈了。

    这样的理论依据是:如果一个数能加入某个集合,这最好。如果不能,那么这个集合中包含两部分:一部分是不能整除的数,可以同当前数组成集合;另一部分数不能。这时,如果我们把这个集合拆成两部分,让当前数加入前者,结果还是有两个集合;而不加入此集合,最坏情况下也还是有两个集合。

    也就是说,只要加入,就只会赚,不会赔。说白了也就是一个贪心。
std:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

int n;
int a[5010];
bool f[5010];
struct point
{
int x;
point *next;
}*p[5010];

bool find(int i,int j)
{
for (point *k=p[j]; k; k=k->next)
if (!(a[i] % k->x)) return 0;
return 1;
}

void insert(int i,int j)
{
point *now=new point;
now->x=a[i]; now->next=p[j]; p[j]=now;
}

int main()
{
freopen("poset.in","r",stdin);
freopen("poset.out","w",stdout);
scanf("%d",&n);
for (int i=1; i<=n; i++)
scanf("%d",&a[i]);
sort(a+1,a+n+1);

for (int i=2; i<=n; i++)
for (int j=1; j<i; j++)
if (!f[j] && (a[i] % a[j]))
if (find(i,j))
{
f[i]=1;
insert(i,j);
break;
}

int ans=0;
for (int i=1; i<=n; i++)
if (!f[i]) ++ans;

printf("%d\n",ans);
fclose(stdin);
fclose(stdout);
return 0;
}

然而貌似DP也可以搞
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

int N,a[5005],f[5005],ans;

int main()
{

freopen("poset.in","r",stdin);
freopen("poset.out","w",stdout);
scanf("%d",&N);
for (int i=1;i<=N;i++) scanf("%d",&a[i]),f[i]=1;

sort(a+1,a+1+N);
for (int i=1;i<=N;i++)
{
for (int j=1;j<i;j++)
{
if (!(a[i] % a[j]))
{
f[i]=max(f[i],f[j]+1);
}
}
ans=max(ans,f[i]);
}
printf("%d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  模拟 DP