| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 42026 人关注过本帖, 47 人收藏
标题:C论坛算法团队 首战 西安电子科技大学OJ
只看楼主 加入收藏
uushuo
Rank: 2
等 级:论坛游民
帖 子:13
专家分:31
注 册:2009-1-22
收藏
得分:0 
Problem 1041 - 女儿岛游记

题目描述:
Description

话说,一日,Qinz大牛游荡到了一个岛上,惊喜地发现这岛就是传说中的“女儿岛”,岛上美女如云,Qinz每日与众美女游山玩水,不亦乐乎。直到有一天,Qinz发现自己的胡子不但不长了反而往下掉,而且体型也发生了变化……Qinz要变成女人了!悲痛之时,女儿岛的岛主—女帝给了Qinz一些药水和一本宝典,并告诉“她”,只要按宝典规定的顺序服下药水就能恢复男儿身。宝典上规定了某些药必须在服用了另一些药的前提下才可服用,不然将产生可怕的反作用(比如变成双性人)。不幸的是,由于年代久远,宝典上的一些字已经模糊不清了,然而服药的顺序只可能有一种。请问Qinz能够根据已知的关系找出这唯一的服药顺序,从而顺利地变回纯爷们吗?(提示:宝典上的条目可能会重复,药水的关系不会形成环)
Input
输入的第一行包含一个整数T,表示有T组数据。
每组数据的第一行包含两个整数N(2≤N≤50),M(0≤M≤60)。分别表示药水的数量和宝典上能够看清的条目数。
接下来的M行,每行两个整数 A B。表示必须服用药水编号为A的药水后才能服用编号为B的药水,药水编号从1到N。
Output
每组数据输出一行,如果Qinz能够确定这唯一的服用顺序,输出该顺序,否则输出-1。
Sample Input
3
2 1
1 2

3 3
3 1
2 1
2 3

4 2
1 2
3 4
Sample Output
1 2
2 3 1
-1

分析过程:
这个题我用了两种方法,第一种方法:建表,采用了类似Pro1037智破机枪阵的方法,用匈牙利算法求出结果,如果最终生成的最大链长度不是N,就输出-1。
代码:
程序代码:
#include <stdio.h>
#include <string.h>
int N,M;
unsigned char map[64][64];
unsigned char exist[64],after[64];

int find(int x)
{
    int i;
    for(i=1;i<=N;i++)
    {
        if( map[i][x] && !exist[i]) {
            exist[i]=1;
            if(after[i]==0 || find(after[i])) {
                after[i]=x;
                return 1;
            }
        }
    }
    return 0;
}
int main(int argc, char *argv[])
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int a,b,i,firstOne=0;
        memset(map,0,sizeof(map));
        memset(after,0,sizeof(after));
        scanf("%d%d",&N,&M);
        for(i=0;i<M;i++) {
            scanf("%d%d",&a,&b);
            map[a][b]=1;
        }
        for(i=1;i<=N;i++)
        {
            memset(exist,0,sizeof(exist));
            if(!find(i)) {
                if(firstOne==0) firstOne=i;
                else {
                    printf("-1");
                    break;
                }
            }
        }
        if(i>N){
            int x=firstOne;
            for(i=1;i<=N;i++)
                printf("%d ",x),x = after[x];
        }
        printf("\n");
    }
    return 0;
}

第二种方法:
见一个数组,list[i]表示i元素应该在第几个出现。不停的刷list的数据,直到不再变化为止。算法复杂度应该是O(N3)吧,但是因为数据量小,所以能过。
如果药典给的提示不够的话,那么list中必然有两个或以上的相同元素,此时也必缺少某个位置应该出现的元素,输出-1
代码:
程序代码:
#include <iostream>
#include <string.h>
int N,M;
int d[64][2];
int list[64];
int ansLst[64];

using namespace std;

bool cal()
{
    bool ans=true;
    for(int i=0;i<M;i++)
    {
        if(list[d[i][0]]>=list[d[i][1]])
        {
            list[d[i][1]]=list[d[i][0]]+1;
            ans = false;
        }
    }
    return ans;
}
bool mkAns()
{
    for(int i=0;i<N;i++)
    {
        int j=1;
        for(j=1;j<=N;j++)
        {
            if(list[j] == i) {
                ansLst[i]=j;
                break;
            }
        }
        if(j>N) return false;
    }
    return true;
}

int main(int argc, char *argv[])
{
    int T;cin>>T;
    while(T--)
    {
        memset(d,0,sizeof(d));
        memset(ansLst,0,sizeof(ansLst));
        memset(list,0,sizeof(list));
        cin>>N>>M;
        for (int i=0; i<M; i++)
        {
            cin>>d[i][0]>>d[i][1];
        }
        while(!cal());
        if(mkAns()){
            for (int i=0; i<N; i++) cout<<ansLst[i]<<' ';
            cout<<endl;
        }else cout<<"-1"<<endl;
    }
}
2013-03-31 21:54
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
欢迎新朋友的加入,好久没整理这贴子了,重新统计一下已完成的题目

1001 1002 1003 1004 1005 1006 1007 1008 1009 1010

1011 1012 1013 1014 1015 1016 1017 1018 1019 1020

1021 1022 1023 1024 1025 1026 1027 1028 1029 1030

1031 1032 1033 1034 1035 1036 1037 1038 1039 1040

1041 1042 1043 1049

1053 1054 1055

1061 1069

1076

1103 1104 1109

1121 1130

1178

1201 1202 1203 1204 1205 1206 1207 1209

1215

重剑无锋,大巧不工
2013-04-04 12:54
mathlover
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2013-4-4
收藏
得分:0 
回楼主。。。1008数星星这题。。我参考了您的代码,可是却屡次WA。。。不知何解,本地测试都和您的答案一样
我的代码是
程序代码:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define INF 1000000000000000.0
#define MAX 1000
#define EPS 1e-10
typedef struct point
{
    int x,y;
}point;
double k[MAX];
int comp(const void * a, const void * b)
{
    if(*(double *)a > *(double *)b) return 1;
    if(*(double *)a < *(double *)b) return -1;
    return 0;
}

int cal(point p[], int n)//主体函数 
{
    int i,j,l,max=0;
    for(i = 0; i < n; i++)
    {
        for(j = i + 1; j < n; j++) 
            k[j-i-1]=(p[i].x==p[j].x)?INF:(p[i].y-p[j].y)*1.0/(p[i].x-p[j].x);//计算斜率 
        qsort(k,n-i-1, sizeof(double),comp);
        for(j = 0; j < n-i;)
        { 
            for(l=j+1;l< n-1;l++)
                if(fabs(k[l]-k[j])>EPS)
                    break;
            max=(l-j>max)?(l-j):max;
            j=l;
        } 
    }
    return max+1;
}
point p[MAX];
main()
{
    int n, i;
    while(~scanf("%d", &n))
    {
        for(i = 0; i < n; i++)
            scanf("%d%d", &p[i].x, &p[i].y);
        if(n<=2)
            printf("%d\n",n);
        else
            printf("%d\n", cal(p,n));
    }
    return 0;
}
2013-04-04 15:37
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 143楼 mathlover
你好,具体问题我标在备注里了,多数是你写的时候笔误造成的,这种bug是不可能通过编译器的语法分析发现的,所以一定要细心。

程序代码:
int cal(point p[], int n)//主体函数
{
    int i,j,l,max=0;
    for(i = 0; i < n; i++)
    {
        for(j = i + 1; j < n; j++)
            k[j-i-1]=(p[i].x==p[j].x)?INF:(p[i].y-p[j].y)*1.0/(p[i].x-p[j].x);//计算斜率
        qsort(k,n-i-1, sizeof(double),comp);
        for(j = 0; j < n-i;)//范围应该是n-i-1,你的范围溢出了
        {
            for(l=j+1;l< n-1;l++)//这个范围就更不对了,应该还是n-i-1
                if(fabs(k[l]-k[j])>EPS)
                    break;
            max=(l-j>max)?(l-j):max;
            j=l;
        }
    }
    return max+1;
}

重剑无锋,大巧不工
2013-04-04 17:13
y3765258
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:106
专家分:172
注 册:2013-4-9
收藏
得分:0 
这里题目果然有难度,我是软件专业的,但是大一新生,会的很少,望多指教。
也有一定编程ACM试题的能力。。。但是遇到哈希数表之类的就算了。

有问题一起探讨,一起进步。
2013-04-10 11:07
dd460215204
Rank: 1
等 级:新手上路
帖 子:5
专家分:0
注 册:2013-4-10
收藏
得分:0 
2013-04-10 22:05
C_戴忠意
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:2
帖 子:575
专家分:1349
注 册:2011-10-21
收藏
得分:0 
回复 144楼 beyondyf
杨大哥,好久不见了。

编程之路定要走完……
2013-04-12 21:53
如蜗牛
Rank: 2
等 级:论坛游民
威 望:1
帖 子:40
专家分:42
注 册:2013-4-12
收藏
得分:0 
回复 2楼 beyondyf
追问:
这个程序在VC6.0上是无法正常运行的,尤其输入多组数据的结束,求楼上大牛解释!!!
2013-04-13 18:37
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 147楼 C_戴忠意
小戴好久不见,忙什么呢?

重剑无锋,大巧不工
2013-04-13 21:20
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
以下是引用如蜗牛在2013-4-13 18:37:41的发言:

追问:
这个程序在VC6.0上是无法正常运行的,尤其输入多组数据的结束,求楼上大牛解释!!!
我不知道你说的是哪个程序,怎么个无法正常运行,也不知道你需要我解释什么,很报歉。

重剑无锋,大巧不工
2013-04-13 21:22
快速回复:C论坛算法团队 首战 西安电子科技大学OJ
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.018724 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved