注:本文是我原先在csdn內寫的一篇博文,現轉到這里,兩篇博文盡量同時更新。
//#include<iostream->shuati>
//define 為什么刷 學長☞hzwer用的測評系統,最近火上了
//define 技術 渣渣


不刷題很不爽啊
那就爽一爽吧
雖然過幾天就不一定會刷了
【1000】a+b問題
......人家提交框都給答案了
【1001】舒適的路線
Z小鎮是一個景色宜人的地方,吸引來自各地的觀光客來此旅游觀光。
Z小鎮附近共有
N(1<N≤500)個景點(編號為1,2,3,…,N),這些景點被M(0<M≤5000)條道路連接着,所有道路都是雙向的,兩個景點之間可能有多條道路。也許是為了保護該地的旅游資源,Z小鎮有個奇怪的規定,就是對於一條給定的公路Ri,任何在該公路上行駛的車輛速度必須為Vi。頻繁的改變速度使得游客們很不舒服,因此大家從一個景點前往另一個景點的時候,都希望選擇行使過程中最大速度和最小速度的比盡可能小的路線,也就是所謂最舒適的路線。
第一行包含兩個正整數,N和M。
接下來的M行每行包含三個正整數:x,y和v(1≤x,y≤N,0 最后一行包含兩個正整數s,t,表示想知道從景點s到景點t最大最小速度比最小的路徑。s和t不可能相同。
如果景點s到景點t沒有路徑,輸出“IMPOSSIBLE”。否則輸出一個數,表示最小的速度比。如果需要,輸出一個既約分數。
樣例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
樣例1
IMPOSSIBLE
樣例2
5/4
樣例3
2
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】搭橋
有一矩形區域的城市中建築了若干建築物,如果某兩個單元格有一個點相聯系,則它們屬於同一座建築物。現在想在這些建築物之間搭建一些橋梁,其中橋梁只能沿着矩形的方格的邊沿搭建,如下圖城市1有5棟建築物,可以搭建4座橋將建築物聯系起來。城市2有兩座建築物,但不能搭建橋梁將它們連接。城市3只有一座建築物,城市4有3座建築物,可以搭建一座橋梁聯系兩棟建築物,但不能與第三座建築物聯系在一起。
在輸入的數據中的第一行包含描述城市的兩個整數r 和c, 分別代表從北到南、從東到西的城市大小(1 <= r <= 50 and 1 <= c <= 50). 接下來的r 行, 每一行由c 個(“#”)和(“.”)組成的字符. 每一個字符表示一個單元格。“#”表示建築物,“.”表示空地。
在輸出的數據中有兩行,第一行表示建築物的數目。第二行輸出橋的數目和所有橋的總長度。
樣例1
3 5
#...#
..#..
#...#
樣例2
3 5
##...
.....
....#
樣例3
3 5
#.###
#.#.#
###.#
樣例4:
3 5
#.#..
.....
....#
樣例1
5
4 4
樣例2
2
0 0
樣例3
1
0 0
樣例4
3
1 1
見描述
我只有幾句話想說。
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】電話連線
一個國家有n個城市。若干個城市之間有電話線連接,現在要增加m條電話線(電話線當然是雙向的了),使得任意兩個城市之間都直接或間接經過其他城市有電話線連接,你的程序應該能夠找出最小費用及其一種連接方案。
輸入文件的第一行是n的值(n<=100).
第二行至第n+1行是一個n*n的矩陣,第i行第j列的數如果為0表示城市i與城市j有電話線連接,否則為這兩個城市之間的連接費用(范圍不超過10000)。
輸出文件的第一行為你連接的電話線總數m,第二行至第m+1行為你連接的每條電話線,格式為i j,(i<j), i j是電話線連接的兩個城市。輸出請按照Prim算法發現每一條邊的順序輸出,起始點為1.
第m+2行是連接這些電話線的總費用。
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
2
1 4
2 5
17
n<=100
【1007】級數求和
已知:Sn= 1+1/2+1/3+…+1/n。顯然對於任意一個整數K,當n足夠大的時候,Sn大於K。
現給出一個整數K(1<=k<=15),要求計算出一個最小的n;使得Sn>K。
鍵盤輸入 k
屏幕輸出 n
1
2
#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;
}
