【codevs】刷題記錄→_→(推薦看!)


注:本文是我原先在csdn內寫的一篇博文,現轉到這里,兩篇博文盡量同時更新。

 

 

//#include<iostream->shuati>

//define 為什么刷  學長☞hzwer用的測評系統,最近火上了

//define 技術  渣渣

 

生氣生氣生氣不刷題很不爽啊

那就爽一爽吧鄙視雖然過幾天就不一定會刷了

 

 

【1000】a+b問題

 

尷尬......人家提交框都給答案了

 

 

【1001】舒適的路線

 

 

題目描述 Description

Z小鎮是一個景色宜人的地方,吸引來自各地的觀光客來此旅游觀光。
Z小鎮附近共有
N(1<N≤500)個景點(編號為1,2,3,…,N),這些景點被M(0<M≤5000)條道路連接着,所有道路都是雙向的,兩個景點之間可能有多條道路。也許是為了保護該地的旅游資源,Z小鎮有個奇怪的規定,就是對於一條給定的公路Ri,任何在該公路上行駛的車輛速度必須為Vi。頻繁的改變速度使得游客們很不舒服,因此大家從一個景點前往另一個景點的時候,都希望選擇行使過程中最大速度和最小速度的比盡可能小的路線,也就是所謂最舒適的路線。

 

輸入描述 Input Description

第一行包含兩個正整數,N和M。
接下來的M行每行包含三個正整數:x,y和v(1≤x,y≤N,0 最后一行包含兩個正整數s,t,表示想知道從景點s到景點t最大最小速度比最小的路徑。s和t不可能相同。

 

輸出描述 Output Description

如果景點s到景點t沒有路徑,輸出“IMPOSSIBLE”。否則輸出一個數,表示最小的速度比。如果需要,輸出一個既約分數。

 

樣例輸入 Sample Input

樣例1
4 2
1 2 1
3 4 2
1 4

樣例2
3 3
1 2 10
1 2 5
2 3 8
1 3

樣例3
3 2
1 2 2
2 3 4
1 3

 

樣例輸出 Sample Output

樣例1
IMPOSSIBLE

樣例2
5/4

樣例3
2

 

數據范圍及提示 Data Size & Hint

N(1<N≤500)

M(0<M≤5000)

Vi在int范圍內

 

 

題解:

1.並查集,記錄起點和終點是不是連通了

2.如果連通了,計算比例值,並更新最優比例值

3.化簡比例值

 

沒啥好說的了。

 

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct node{
    int x,y,v;
}a[5001];

int n,m,fa[501],s,t,ma=0xfffffff,mi=1;//0xfffffff原值約為268435455
double ljj,pjy;

int ask(int x){return fa[x]==x ? x : fa[x]=ask(fa[x]);}

bool cmp(node a,node b){return a.v<b.v;}

int sift(int x,int y){return x%y==0 ? y : sift(y,x%y);}

int main(){
    int i,j,p,q;
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].v);
    scanf("%d%d",&s,&t);
    sort(a+1,a+1+m,cmp);
    for(i=1;i<=m;i++)
    {
        for(j=1;j<=n;j++) fa[j]=j;
        for(j=i;j>0;j--)
        {
            p=ask(a[j].x);q=ask(a[j].y);
            fa[q]=p;
            if(ask(s)==ask(t))//看看兩個景點是否連上了?連上了就開始算咯
            {
                ljj=ma*1.0/mi;
                pjy=a[i].v*1.0/a[j].v;////由於前面已經對a數組中的v排序,因此數據已經按照車輛行駛速度從小到大排序,因為j<=i,因此a[i].v*1.0/a[j].v>=1
                if(ljj>pjy){ma=a[i].v;mi=a[j].v;}//如果原比例值比先比例值大就更新比例
            }
        }
    }
    int syf=sift(ma,mi);//約分,求兩數最大公倍數 
    ma/=syf;mi/=syf;
    if(ma==0xfffffff) printf("IMPOSSIBLE\n");
    else if(mi==1) printf("%d\n",ma);
    else printf("%d/%d\n",ma,mi);
    return 0;
}

  

 

【1002】搭橋

 

 

題目描述 Description

有一矩形區域的城市中建築了若干建築物,如果某兩個單元格有一個點相聯系,則它們屬於同一座建築物。現在想在這些建築物之間搭建一些橋梁,其中橋梁只能沿着矩形的方格的邊沿搭建,如下圖城市1有5棟建築物,可以搭建4座橋將建築物聯系起來。城市2有兩座建築物,但不能搭建橋梁將它們連接。城市3只有一座建築物,城市4有3座建築物,可以搭建一座橋梁聯系兩棟建築物,但不能與第三座建築物聯系在一起。

 

輸入描述 Input Description

在輸入的數據中的第一行包含描述城市的兩個整數r 和c, 分別代表從北到南、從東到西的城市大小(1 <= r <= 50 and 1 <=  c <= 50). 接下來的r 行, 每一行由c 個(“#”)和(“.”)組成的字符. 每一個字符表示一個單元格。“#”表示建築物,“.”表示空地。

 

 

輸出描述 Output Description

在輸出的數據中有兩行,第一行表示建築物的數目。第二行輸出橋的數目和所有橋的總長度。

 

樣例輸入 Sample Input

樣例1

3 5

#...#

..#..

#...#

 

樣例2

3 5

##...

.....

....#

 

樣例3

3 5

#.###

#.#.#

###.#

 

樣例4:

3 5

#.#..

.....

....#

 

 

樣例輸出 Sample Output

樣例1

5

4 4

 

樣例2

2

0 0

 

樣例3

1

0 0

 

樣例4

3

1 1

 

數據范圍及提示 Data Size & Hint

見描述

 

 

 

我只有幾句話想說。

 

1.此題變態

2.輸入比較坑,注意輸入

for(int i=1;i<=n;i++){
    for(int j=1;j<=m;j++){
        scanf(" %c",&map[i][j]);
        if(map[i][j]=='#') a[++cntn]=p(i,j);
    }
}

也不知咋地,輸入map[i][j]時占位符前面必須加一個空格(可能是吃空行吧,但如果前面是字符呢?),或者改成cin>>map[i][j]。之前因為這個scanf的占位符問題WA了不少次,反正我只想做這個動作:鄙視

 

3.解答如下

    第一問等於細胞,第二問等於最小生成樹。

    當然我用的是並查集+最小生成樹

    之后跑一遍並查集數組即可,輸出前給並查集數組排個序。

 

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define maxn 51*51
using namespace std;
const int dx[8]={-1,0,1,1,1,0,-1,-1};
const int dy[8]={-1,-1,-1,0,1,1,1,0};

struct edge{
    int l,r,w;
    bool operator < (const edge an)const{
        return w<an.w;
    }
}e[maxn*100];

int cnt,n,m,a[maxn],tot,f[maxn],ans,sum,cntn;
bool vis[maxn];
char map[60][60];

int find(int x){return x==f[x] ? x : f[x]=find(f[x]);}

int p(int i,int j){return (i-1)*m+j;}

inline void add(int i,int j,int k,int l){ 
    e[++cnt].l=p(i,j);
    e[cnt].r=p(k,l);
    e[cnt].w=l-j-1;
}

inline void add2(int i,int j,int k,int l){ 
    e[++cnt].l=p(i,j);
    e[cnt].r=p(k,l);
    e[cnt].w=k-i-1;
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf(" %c",&map[i][j]);
            if(map[i][j]=='#') a[++cntn]=p(i,j);
        }
    }
    for(int i=1;i<=cntn;i++) f[a[i]]=a[i];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(map[i][j] == '#')
            for(int k=0;k<8;k++)//向八面擴展 
                if(map[i+dx[k]][j+dy[k]] == '#')
                {
                    int f1=find(p(i,j)),f2=find(p(i+dx[k],j+dy[k]));
                    f[f2]=f1;
                }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(map[i][j] == '#')
                for(int k=j;k<=m;k++)
                {
                    if(map[i][k]=='#') add(i,j,i,k);
                    if(map[i+1][k]=='#') add(i,j,i+1,k);
                    if(map[i-1][k]=='#') add(i,j,i-1,k);
                }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(map[i][j]=='#')
                for(int k=i;k<=n;k++)
                {
                    if(map[k][j]=='#') add2(i,j,k,j);
                    if(map[k][j-1]=='#') add2(i,j,k,j-1);
                    if(map[k][j+1]=='#') add2(i,j,k,j+1);
                }
    for(int i=1;i<=cntn;i++)
        if(!vis[find(a[i])]) tot++,vis[find(a[i])]=1;
    sort(e+1,e+1+cnt);
    for(int i=1;i<=cnt;i++)
    {
        int f1=find(e[i].l),f2=find(e[i].r);
        if(f1==f2) continue;
        if(e[i].w) ans++;
        sum+=e[i].w;
        f[f2]=f1;
    }
    printf("%d\n%d %d\n",tot,ans,sum);
    return 0;
}

  

 

【1003】電話連線

 

 

題目描述 Description

一個國家有n個城市。若干個城市之間有電話線連接,現在要增加m條電話線(電話線當然是雙向的了),使得任意兩個城市之間都直接或間接經過其他城市有電話線連接,你的程序應該能夠找出最小費用及其一種連接方案。

 

輸入描述 Input Description

    輸入文件的第一行是n的值(n<=100).

    第二行至第n+1行是一個n*n的矩陣,第i行第j列的數如果為0表示城市i與城市j有電話線連接,否則為這兩個城市之間的連接費用(范圍不超過10000)。

 

輸出描述 Output Description

       輸出文件的第一行為你連接的電話線總數m,第二行至第m+1行為你連接的每條電話線,格式為i j,(i<j), i j是電話線連接的兩個城市。輸出請按照Prim算法發現每一條邊的順序輸出,起始點為1.

       第m+2行是連接這些電話線的總費用。

 

樣例輸入 Sample Input

5

0 15 27 6 0

15 0 33 19 11

27 33 0 0 17

6 19 0 0 9

0 11 17 9 0

 

樣例輸出 Sample Output

2

1 4

2 5

17

 

數據范圍及提示 Data Size & Hint

n<=100

 

【1007】級數求和

 

題目描述 Description

已知:Sn= 1+1/2+1/3+…+1/n。顯然對於任意一個整數K,當n足夠大的時候,Sn大於K。
         現給出一個整數K(1<=k<=15),要求計算出一個最小的n;使得Sn>K。

 

輸入描述 Input Description

鍵盤輸入 k

 

輸出描述 Output Description

屏幕輸出 n

 

樣例輸入 Sample Input

1

 

樣例輸出 Sample Output

2

 

直接while循環累加,累加超過k就停下。
 
#include<iostream>
using namespace std;
double k,go,m=1.0;
int n;
int main(){
    cin>>k;
    while(go<=k){
        go+=1/m;
        m+=1.0;
        n++;
    }
    cout<<n;
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM