19/7/2012 ICPC培训 第四天

今天只刷出来三题大哭

明天下午组内又有测试了,肿么办呀,搜索和DP。

说说今天吧。

这三题都是以前看过但没做出来的题,也根本就没尝试去做,就觉得做不出来!

第一题(HDU4039)。

这题花了6个小时左右抓狂。其实,前两个小时代码就搞定了,可是有一处小错,一直TLE呀。

在Floyd()中把两个if判断条件没写好呀。明明算法是对的,可是代码逻辑就是没能那样写出来!

这种错误还很难找!!!

这题听说可以用搜索,可是木有思路。于是乎,我就建图了,然后借用Floyd算法搞定的。当然,

这其中还有怎么按字典序输出,怎么判断要输出的个数以及怎么控制按格式输出。

代码:

也可以看看这个代码:点击打开链接

#include<iostream>
using namespace std;

const int maxLen=16;
const int maxNum=2001;

bool map[maxNum][maxNum];  //建图 
int result[maxNum][maxNum];  //result[i][j]表示i、j的共同朋友数 
int numOfRelation,quary,numOfName,cas=1;
char temp[maxNum][maxLen];  //存放字典序的人 

struct node
{
    char front[maxLen];
    char back[maxLen];
}help[maxNum/2];  //暂时存放朋友关系 

int findIndex(char c[])  //寻找ch[]在temp[]中的下标 
{
    for(int i=0;i<numOfName;i++)
    {
        if(strcmp(c,temp[i])==0)
        {
            return i;
        }
    }
    
    return -1;
}
    
void initInput()  //输入认识关系,并将不同的人存放在temp[]中 
{
    int index;
    
    numOfName=0;   //存放在temp[]中的不同名字个数 
    for(int i=0;i<numOfRelation;i++)
    {
        scanf("%s%s",&help[i].front,&help[i].back);
        
        index=findIndex(help[i].front);
        if(index==-1)
        {
            strcpy(temp[numOfName++],help[i].front);
        }
        
        index=findIndex(help[i].back);
        if(index==-1)
        {
            strcpy(temp[numOfName++],help[i].back);
        }
    }   
}

void bubbleSort()  //将temp中的人按字典序排序 
{
    char ch[maxLen];
    
    for(int i=0;i<numOfName;i++)
    {
        for(int j=numOfName-1;j>i;j--)
        {
            if(strcmp(temp[j],temp[j-1])==-1)  //temp[j]<temp[j-1] 
            {
                strcpy(ch,temp[j]);
                strcpy(temp[j],temp[j-1]);
                strcpy(temp[j-1],ch);
            }
        }
    }
}

void buildMap()   //建图 ,无向图 
{
    memset(map,false,sizeof(map));
    
    int row,col;
    for(int i=0;i<numOfRelation;i++)
    {
        row=findIndex(help[i].front);
        col=findIndex(help[i].back);
        
        if(row!=col)   //题目要求,自己和自己不是朋友 
        {
            map[row][col]=map[col][row]=true;
        }
    }    
}      
 
void Floyd()  //算法变形,加优化 
{
    memset(result,0,sizeof(result));
    
    for(int k=0;k<numOfName;k++) 
    { 
        for(int i=0;i<numOfName;i++)
        {
            //if(i==k) continue; 
            if(!map[i][k]) continue; 
            for(int j=0;j<numOfName;j++)
            {
                //if(j==k || j==i) continue; 
                if(map[k][j] && !map[i][j] && i!=j)  //k就是i、j都认识的人 
                {
                    result[i][j]++;
                }
            }
        }
    }
}               

void output()  //输出 
{
    printf("Case %d:\n",cas++);
    
    char ch[maxLen];
    int index,maxResult,i,j;
    
    for(i=0;i<quary;i++)
    {
        scanf("%s",&ch);
        
        index=findIndex(ch);
        
        maxResult=0; 
        for(j=0;j<numOfName;j++)
        {
            if(index!=j)
            { 
                maxResult=maxResult>result[index][j]?maxResult:result[index][j];
            } 
        }
        
        if(maxResult==0)
        {
            printf("-\n");
            continue;
        }
        
        int num=0;
        int rem[maxNum/2]; 
        for(j=0;j<numOfName;j++)
        {
            if(index!=j && maxResult==result[index][j])
            {
                rem[num++]=j; 
            }
        }
        
        for(j=0;j<num-1;j++)
        {
            printf("%s ",temp[rem[j]]);
        } 
        printf("%s\n",temp[rem[num-1]]);
    }
}       

/* 
  也可以去掉注释,然后把函数Floyd()和output()注释
  掉,同样能过,当然主函数中的调用也要注释掉,另外,
  全局变量result[][]也注释掉 
  
void getResult()
{
    printf("Case %d:\n",cas++);
    
    int index,maxResult,i,j,k;
    char ch[maxLen]; 
    int result[maxNum],rem[maxNum/2]; 
     
    for(i=0;i<quary;i++)
    { 
        maxResult=0;
        memset(result,0,sizeof(result));
        
        scanf("%s",&ch);
        
        index=findIndex(ch);
        
        for(j=0;j<numOfName;j++)
        {
            if(!map[index][j]) continue; 
            for(k=0;k<numOfName;k++)
            {
                if(!map[j][k] || map[index][k] || index==k) continue;
                
                result[k]++;
                
                maxResult=maxResult>result[k]?maxResult:result[k];
            }
        }
        
        if(maxResult==0)
        {
            printf("-\n");
            continue;
        }
        
        int num=0;
        for(j=0;j<numOfName;j++)
        {
            if(index!=j && maxResult==result[j])
            {
                rem[num++]=j; 
            }
        }
        
        for(j=0;j<num-1;j++)
        {
            printf("%s ",temp[rem[j]]);
        } 
        printf("%s\n",temp[rem[num-1]]);
    }
}      
*/ 
                          
int main()
{
    int tCase;
    
    scanf("%d",&tCase); 
    while(tCase--)
    {
        scanf("%d%d",&numOfRelation,&quary);
        
        initInput();
        
        bubbleSort();
        
        buildMap();
        
        Floyd();
           
        output();
        
        //getResult();
    }
    
    return 0;
}

第二题(HDU1572)

个人觉得这题意思不是很清楚,没说是否可以重复走。其他就是暴力dfs了。

代码:

#include<iostream>
#include<cstring>
using namespace std;

const int INF=0x7fffffff;
const int maxCity=30;
const int maxPeople=7;

double map[maxCity][maxCity],minLen;
bool visit[maxCity][maxCity],canVisit[maxCity];
int exist[maxPeople];
int nCity,nPeople;

void input()
{
    for(int i=0;i<nCity;i++)
    {
        for(int j=0;j<nCity;j++)
        {
            cin>>map[i][j];
        }
    }
    
    cin>>nPeople;
    
    for(int j=0;j<nPeople;j++)
    {
        cin>>exist[j];
    }
}

bool visitAll()
{
    for(int i=0;i<nPeople;i++)
    {
        if(canVisit[exist[i]]==false)
        {
            return false;
        }
    }
    
    return true;
}

bool notVisit(int x)
{
    if(canVisit[x]==false)
    {
        return true;
    }
    
    return false;
}

void dfs(int x,double len)
{
    if(visitAll())
    {
        minLen=minLen>len?len:minLen;
        return;
    }
    
    for(int i=0;i<nPeople;i++)
    {        
        if(!visit[x][exist[i]] && notVisit(exist[i]))
        {
            canVisit[exist[i]]=true;
            visit[x][exist[i]]=true;
            len+=map[x][exist[i]];
            dfs(exist[i],len);
            canVisit[exist[i]]=false;
            visit[x][exist[i]]=false;
            len-=map[x][exist[i]];
        }
    }
}
  
int main()
{
    while(cin>>nCity,nCity)
    {
        input();
        
        minLen=INF;
        memset(canVisit,false,sizeof(canVisit));
        canVisit[0]=true;
        memset(visit,false,sizeof(visit));
        visit[0][0]=true;
        dfs(0,0);
        
        cout<<minLen<<endl;
    }
    
    return 0;
}

第三题(HDU1372)

这题看过一直没明白啥意思!马走日就马走日呗,还说的那么复杂。自己英语不好,还搞啥那么

那么难懂的英语。

苦逼的是,刚开始居然想着用dfs来写,结果你懂的,半天没出结果。2B了。。。

然后用bfs加上优先级队列过了。

代码:

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
 
const int len=9;
const int INF=0x7fffffff;
const int help[][2]={{1,-2},{2,-1},{2,1},{1,2},{-1,2},{-2,1},{-2,-1},{-1,-2}};
 
bool visit[len][len],flag;
int minStep;
 
struct node
{
    int x,y,step;
    
    friend bool operator < (const node a,const node b)
    {
        return a.step>b.step;
    } 
}start,end;

bool canVisit(int x,int y)
{
    if(x>=1 && x<=8 && y>=1 && y<=8 && !visit[x][y])
    {
        return true;
    }
    
    return false;
}
 
 void bfs()
 {
    memset(visit,false,sizeof(visit));
    visit[start.x][start.y]=true;
    
    priority_queue<node> myQ;
    myQ.push(start);
    
    node temp1,temp2;
    flag=false;
    minStep=0;
    while(!myQ.empty() && !flag)
    {
        temp1=myQ.top();
        myQ.pop(); 
        
        for(int i=0;i<8;i++)
        {
            temp2.x=temp1.x+help[i][0];
            temp2.y=temp1.y+help[i][1];
            
            if(!canVisit(temp2.x,temp2.y)) continue;
            
            visit[temp2.x][temp2.y]=true; 
            temp2.step=temp1.step+1; 
            
            if(temp2.x==end.x && temp2.y==end.y)
            {
                flag=true;
                minStep=temp2.step; 
                continue; 
            }
            
            myQ.push(temp2); 
        }
     }
} 
         
 int main()
 {
    char ch1[3],ch2[3];
    
    while(cin>>ch1>>ch2)
    {
        start.y=ch1[0]-'a'+1;
        start.x=ch1[1]-'0';
        start.step=0;
        end.y=ch2[0]-'a'+1;
        end.x=ch2[1]-'0';
        
        bfs(); 
        
        cout<<"To get from "<<ch1<<" to "<<ch2<<" takes "<<minStep<<" knight moves."<<endl; 
    }
    
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值