北京大學ACM-ICPC競賽訓練暑期課
全排列 (遞迴DFS)
描述
給定一個由不同的小寫字母組成的字串,輸出這個字串的所有全排列。 我們假設對於小寫字母有'a' < 'b' < ... < 'y' < 'z',而且給定的字串中的字母已經按照從小到大的順序排列。
輸入輸入只有一行,是一個由不同的小寫字母組成的字串,已知字串的長度在1到6之間。輸出輸出這個字串的所有排列方式,每行一個排列。要求字母序比較小的排列在前面。字母序如下定義:
已知S = s1s2...sk, T = t1t2...tk,則S < T 等價於,存在p (1 <= p <= k),使得
s1= t1, s2= t2, ..., sp - 1
abc
樣例輸出
abc acb bac bca cab cba
#include <bits/stdc++.h> using namespace std; string str,sub; int a[50000+5],cnt=0,n; string ch[720]; void dfs(int k,string &sub) { //cout<<k<<endl; if(k==n) { cout<<sub<<endl; returnView Code; } for(int i=0;i<n;i++) { if(!a[i]) { string xx; xx=sub; sub+=str[i]; a[i]=1;cnt++; dfs(cnt,sub); a[i]=0;cnt--; sub=xx; } } } int main() { int m,l,r; cin>>str; memset(a,0,sizeof(a)); n= str.size(); sub=""; dfs(cnt,sub); return 0; }
冰闊落 I
描述
老王喜歡喝冰闊落。
初始時刻,桌面上有n杯闊落,編號為1到n。老王總想把其中一杯闊落倒到另一杯中,這樣他一次性就能喝很多很多闊落,假設杯子的容量是足夠大的。
有m次操作,每次操作包含兩個整數x與y。
若原始編號為x的闊落與原始編號為y的闊落已經在同一杯,請輸出"Yes";否則,我們將原始編號為y所在杯子的所有闊落,倒往原始編號為x所在的杯子,並輸出"No"。
最後,老王想知道哪些杯子有冰闊落。
輸入有多組測試資料,少於 5 組。
每組測試資料,第一行兩個整數 n, m (n, m<=50000)。接下來 m 行,每行兩個整數 x, y (1<=x, y<=n)。輸出每組測試資料,前 m 行輸出 "Yes" 或者 "No"。
第 m+1 行輸出一個整數,表示有闊落的杯子數量。
第 m+2 行有若干個整數,從小到大輸出這些杯子的編號。樣例輸入
3 2 1 2 2 1 4 2 1 2 4 3
樣例輸出
No Yes 2 1 3 No No 2 1 4
#include <bits/stdc++.h> using namespace std; string str; int a[50000+5],cnt; int root(int x) { if(a[x]==x) return x; return root(a[x]); } void find(int l,int r) { int ll=root(l),rr=root(r); if(ll==rr) { printf("Yes\n"); //cout<<"Yes"<<endl; } else { a[rr] =ll; cnt--; //cout<<"No"<<endl; printf("No\n"); } } int main() { int m,n,l,r; while(scanf("%d %d",&n,&m)!=EOF) { cnt=n; for(int i=1;i<=n;i++) { a[i]=i; } for(int i=1;i<=m;i++) { scanf("%d %d",&l,&r); //cin>>l>>r; find(l,r); } printf("%d\n",cnt); //cout<<cnt<<endl; for(int i=1;i<=n;i++) if(a[i]==i) printf("%d ",i);//cout<<i<<" "; //cout<<endl; printf("\n"); } return 0; }View Code
開餐館
描述
北大資訊學院的同學小明畢業之後打算創業開餐館.現在共有n個地點可供選擇。小明打算從中選擇合適的位置開設一些餐館。這n個地點排列在同一條直線上。我們用一個整數序列m1, m2, ... mn來表示他們的相對位置。由於地段關係,開餐館的利潤會有所不同。我們用pi表示在mi處開餐館的利潤。為了避免自己的餐館的內部競爭,餐館之間的距離必須大於k。請你幫助小明選擇一個總利潤最大的方案。
輸入標準的輸入包含若干組測試資料。輸入第一行是整數T (1 <= T <= 1000) ,表明有T組測試資料。緊接著有T組連續的測試。每組測試資料有3行,
第1行:地點總數 n (n < 100), 距離限制 k (k > 0 && k < 1000).
第2行:n 個地點的位置m1 , m2, ... mn ( 1000000 > mi > 0 且為整數,升序排列)
第3行:n 個地點的餐館利潤p1 , p2, ... pn ( 1000 > pi > 0 且為整數)輸出對於每組測試資料可能的最大利潤樣例輸入
2 3 11 1 2 15 10 2 30 3 16 1 2 15 10 2 30
樣例輸出
40 30
#include <bits/stdc++.h> using namespace std; int dp[100+5]; struct node { int v,h; } no[100+5]; int main() { int t,n,m; cin>>t; while(t--) { cin>>n>>m; for(int i=1;i<=n;i++) scanf("%d",&no[i].v ); for(int i=1;i<=n;i++) scanf("%d",&no[i].h ); if(m>no[n].v) { int mx=-1000; for(int i=1;i<=n;i++) mx=max(no[i].h,mx); printf("%d\n",mx); } else { for(int i=1;i<=n;i++) { dp[i] = no[i].h; int mx = no[i].v , mk = no[i].h ; for(int j=1;j<i;j++) { if( no[i].v - no[ j ].v > m ) { dp[ i ] = max( dp[i] ,dp[j] + mk ); } } } cout<<*max_element(dp+1,dp+n+1)<<endl; } } return 0; }View Code
輸出前k大的數
描述
給定一個數組,統計前k大的數並且把這k個數從大到小輸出。
輸入第一行包含一個整數n,表示陣列的大小。n < 100000。
第二行包含n個整數,表示陣列的元素,整數之間以一個空格分開。每個整數的絕對值不超過100000000。
第三行包含一個整數k。k < n。輸出從大到小輸出前k大的數,每個數一行。樣例輸入
10 4 5 6 9 8 7 1 2 3 0 5
樣例輸出
9 8 7 6 5
#include<bits/stdc++.h> #include<stdio.h> #include<iostream> using namespace std; int n,k; int a[100000+5]; void find(int l,int r,int ans) { if(l>=r) return ; int ll=l,rr=r; while(l!=r) { while(l<r && a[l]<=a[r]) r--; swap(a[l],a[r]); while(l<r && a[l]<=a[r]) l++; swap(a[l],a[r]); } if(rr-l+1 == ans) return ; rr-l+1 < ans ? find(ll,l-1,ans-(rr-l+1)) :find(l+1,rr,ans); } int main() { cin>>n; for(int i=0;i<n;i++) cin>>a[i]; cin>>k; find(0,n-1,k); sort(a+n-k,a+n); for(int t=n-1;t>=n-k;t--) cout<<a[t]<<endl; return 0; }View Code
滑雪
描述Michael喜歡滑雪百這並不奇怪, 因為滑雪的確很刺激。可是為了獲得速度,滑的區域必須向下傾斜,而且當你滑到坡底,你不得不再次走上坡或者等待升降機來載你。Michael想知道載一個區域中最長的滑坡。區域由一個二維陣列給出。陣列的每個數字代表點的高度。下面是一個例子
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
一個人可以從某個點滑向上下左右相鄰四個點之一,當且僅當高度減小。在上面的例子中,一條可滑行的滑坡為24-17-16-1。當然25-24-23-...-3-2-1更長。事實上,這是最長的一條。輸入輸入的第一行表示區域的行數R和列數C(1 <= R,C <= 100)。下面是R行,每行有C個整數,代表高度h,0<=h<=10000。輸出輸出最長區域的長度。樣例輸入
5 5 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9
樣例輸出
25
#include <bits/stdc++.h> using namespace std; int dir[4][2]={-1,0,0,1,1,0,0,-1}; int a[101][101],len[101][101]; int n,m; int dfs(int x,int y) { if(len[x][y]) return len[x][y]; int mx=0,s; for(int i=0;i<4;i++) { int nx=x+dir[i][0],ny=y+dir[i][1]; if(nx>=0 && nx<n && ny>=0 && ny<m && a[nx][ny] < a[x][y]) { s=dfs(nx,ny); if(s>mx) mx=s; } } return len[x][y] = mx+1; } int main() { int mx=-1; cin>>n>>m; memset(len,0,sizeof(len)); for(int i=0;i<n;i++) for(int j=0;j<m;j++) cin>>a[i][j]; for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(dfs(i,j) > mx) mx=len[i][j]; cout<<mx<<endl; return 0; }View Code