校赛个人赛第三场部分解题报告(A,D,F,I)

这次我完成了四道题分别是A,D,F,I

一大半时间我都花在了A上,我犯了很究级的错误

首先是VC6.0的algorithm里没有min函数,而我用min做变量名导致CE4次,找了半天才找出来

其次是我的最短路算法中错误和初始化错误交替出现导致的6次WA

A. The K-th City

A题的大意是给出几个城市之间的距离,要求算出第k远的城市因为数据量较小,可以用floyd或dijkstra算法

floyd版:

#include<iostream>
#include<algorithm>
using namespace std;
struct Pos
{
    long pos;
    long dis;
};
bool cmpFun(Pos a,Pos b)
{
    if(a.dis == b.dis)
        return a.pos < b.pos;
    else
        return a.dis < b.dis;
}
Pos pos[201];
long mini[201][201];
int main()
{
    long n,m;
    while(cin>>n,n)
    {
        cin>>m;
    int i,j,k;
    for(i = 0 ; i < n ; i ++)
    {
        mini[i][i] = 0;
    for(j = i + 1 ; j < n ; j ++)
        mini[i][j] = mini[j][i] = 100000000;
    }
    while(m --)
    {
        scanf("%d %d %d",&i,&j,&k);
        if(mini[i][j] > k)
        mini[i][j] = mini[j][i] = k;
    }
    for (k=0;k<n;k++)
        for (i=0;i<n;i++)
            for (j=0;j<n;j++)
                if (mini[i][k]+mini[k][j]<mini[i][j])
                    mini[i][j] = mini[j][i] =mini[i][k]+mini[k][j];
    for(i = 1 ; i < n ; i ++)
    {
        pos[i - 1].pos = i;
        pos[i - 1].dis = mini[0][i];
    }
    sort(pos,pos + n - 1 ,cmpFun);
    cin>>i;
    cout<<pos[i - 1].pos<<" "<<pos[i - 1].dis<<endl;
    }
    return 0;
}

dijkstra版:

#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 201
#define inf 1000000000
typedef long elem_t;
void dijkstra(int n,elem_t mat[][MAXN],int s,elem_t* minNum,int* pre){
    int v[MAXN],i,j,k;
    for (i=0;i<n;i++)
        minNum[i]=inf,v[i]=0,pre[i]=-1;
    for (minNum[s]=0,j=0;j<n;j++){
        for (k=-1,i=0;i<n;i++)
            if (!v[i]&&(k==-1||minNum[i]<minNum[k]))
                k=i;
        for (v[k]=1,i=0;i<n;i++)
            if (!v[i]&&minNum[k]+mat[k][i]<minNum[i])
                minNum[i]=minNum[k]+mat[pre[i]=k][i];
    }
}
struct Pos
{
    long pos;
    long dis;
};
bool cmpFun(Pos a,Pos b)
{
    if(a.dis == b.dis)
        return a.pos < b.pos;
    else
        return a.dis < b.dis;
}
Pos pos[MAXN];
long matNum[MAXN][MAXN];
long mini[MAXN];
int preNode[MAXN];
int main()
{
    long n,m;
    while(cin>>n,n)
    {
        cin>>m;
        int i,j,k;

        for(i = 0 ; i < n ; i ++)
            for(j = 0 ; j < n ; j ++)
                matNum[i][j] = inf;
        while(m --)
        {
            scanf("%d %d %d",&i,&j,&k);
            matNum[i][j] = matNum[j][i] = k;
        }
        dijkstra(n,matNum,0,mini,preNode);
        for(i = 1 ; i < n ; i ++)
        {
            pos[i - 1].pos = i;
            pos[i - 1].dis = mini[i];
        }
        sort(pos,pos + n - 1 ,cmpFun);
        cin>>i;
        cout<<pos[i - 1].pos<<endl;
    }
    return 0;
}

D. City Mapping

D题是按输入的方向走,输出走过的路径和路径的模式(横向街道,纵向街道,十字路口)

这题只要纯模拟就能过

代码:

#include<iostream>
#include<cstring>
using namespace std;
int strees[201][201][2];
int main()
{
    long m,n,i,j,k;
    long posX,posY;
    long t = 1,tmpInt;
    char cmd[10];
    while(cin>>m>>n>>i,m || n || i)
    {
        memset(strees,0,sizeof(strees));
        posX = posY = 0;
        printf("Scenario #%ld:\n" , t ++);
        while(i --)
        {
            scanf("%s %d",cmd,&tmpInt);
            if(!strcmp(cmd,"South"))
            {
                for( j = posY ; j <= posY + tmpInt ; j ++)
                    strees[posX][j][1] = 1;
                posY = j - 1;
            }
            else if(!strcmp(cmd,"North"))
            {
                for( j = posY ; j >= posY - tmpInt ; j --)
                    strees[posX][j][1] = 1;
                posY = j + 1;
            }
            else if(!strcmp(cmd,"West"))
            {
                for( j = posX ; j >= posX - tmpInt ; j --)
                    strees[j][posY][0] = 1;
                posX = j + 1;
            }
            else if(!strcmp(cmd,"East"))
            {
                for( j = posX ; j <= posX + tmpInt ; j ++)
                    strees[j][posY][0] = 1;
                posX = j - 1;
            }
        }
        for(j = 0 ; j < m ; j ++)
        {
            for(k = 0 ; k < n ; k ++)
                if(strees[k][j][0] && strees[k][j][1])
                    printf("+");
                else if(strees[k][j][0])
                    printf("-");
                else if(strees[k][j][1])
                    printf("|");
                else
                    printf(".");
            printf("\n");
        }
    }
    return 0;
}

F. Tetris

F是简单的俄罗斯方块:

要求按顺序输入方块的其始位置和终点位置,算出最高点

这题可以列一个转移方程,

令第i个方块的最高点为a[i]

=> a[i] = max{a[k] + h[i]}其中h[i]为第i个方块的高度,k<i,且k满足s[i] <= e[k] && e[i] >= s[k]

或 s[i] <= s[k] && e[i] >= e[k]

代码如下:

#include<iostream>
using namespace std;
long s[1001],e[1001],h[1001];
long posH[1001];
int main()
{
    long n,w;
    while(cin>>n>>w , n || w)
    {
        int i,j;
        for(i = 0 ; i < n ; i ++)
            scanf("%ld %ld %ld",&s[i],&e[i],&h[i]);
        memset(posH,0,sizeof(posH));
        long maxInt = 0,tmpInt;
        for(i = 0 ; i < n ; i ++)
        {
            tmpInt = h[i];
            for(j = 0 ; j < i ; j ++)
            {
                if((s[i] <= e[j] && e[i] >= s[j]
                  || s[i] <= s[j] && e[i] >= e[j])
                  && tmpInt < posH[j] + h[i])
                    tmpInt = posH[j] + h[i];
            }
            posH[i] = tmpInt;
        }
        for(i = 0 ; i < n ; i ++)
            if(maxInt < posH[i])
                maxInt = posH[i];
        cout<<maxInt<<endl;
    }
    return 0;
}

I. Girl Friend

I题比较有意思,是帮一个倒霉孩子找女朋友,要求概率*好感度(暂且这么翻译吧)

这是DP问题,令每个女孩的好感度为s[i],成为女朋友的概率为pl[i],第一个见面的美女的最大好感度为a[i]

=>a[i] = max{a[i + 1] * (1 – pl[i]) + s[i] * pl[i] , a[i + 1]}复杂度O(n)

具体代码如下:

#include<iostream>
using namespace std;
double a[100001],pl[100001];
double s[100001];
int main()
{
    int n;
    while(cin>>n,n)
    {
        long i;
        for(i = 0 ; i < n ; i ++)
        {
            scanf("%lf %lf",&pl[i],&s[i]);
            pl[i] /= 100;
        }
        a[n - 1] = s[n - 1] * pl[n - 1];
        for(i = n - 2 ; i >=0 ; i --)
            if(a[i + 1] * (1.0 - pl[i]) + pl[i] * s[i] > a[i + 1])
                a[i] = a[i + 1] * (1 - pl[i]) + pl[i] * s[i];
            else
                a[i] = a[i + 1];
        double output = 0;
        for(i = 0 ; i < n ; i ++)
            if(output < a[i])
                output = a[i];
        printf("%.2lf\n",output);
    }
    return 0;
}