###連接 [https://hihocoder.com/contest/offers97/problems] ###題意 題目1 : 放置矩形 時間限制:10000ms 單點時限:1000ms 內存限制:256MB 描述 小Hi計劃在笛卡爾平面中依次放置N個2x1的矩形(矩形的長是2,寬是1,長寬分別與XY軸平行)。其中第i個矩形的左下角預計放置在座標(Xi, Yi)的位置上。ios
若是放置某一個矩形時,發現會與以前放置的矩形相交(公共面積大於0),就放棄放置當前矩形,繼續嘗試下一個矩形。c++
給定N個矩形的放置順序,請你幫小Hi計算他一共能放下多少個矩形?優化
輸入 第一行包含一個整數N。spa
如下N行包含N對整數Xi, Yi。code
1 <= N <= 100000內存
0 <= Xi, Yi <= 1000000ci
輸出 一個整數表明答案get
樣例輸入 3
0 0 1 0
2 0 樣例輸出 2 ###分析 就是關鍵怎麼判斷咱們當前放置的是否和已經放的有重疊 想一下重疊的狀況是什麼樣的? 因爲滅有相同的x,y,重疊的狀況就是你那個第一條線放在已經放的中間線或者你中間線放置在已經放的第一條線 用一個set維護每一行的情況,後面新來就判斷是否重疊便可,看代碼吧 ###代碼it
#include <bits/stdc++.h> using namespace std; const int N=1e6+10; int n,ans; set<int>st[N]; int main() { //freopen("in.txt","r",stdin); scanf("%d",&n); for(int i=1,x,y; i<=n; i++) { scanf("%d%d",&x,&y); if(st[y].find(x)==st[y].end()&&st[y].find(x+1)==st[y].end()){ st[y].insert(x); st[y].insert(x+1); ans++; } } printf("%d\n",ans); }
題目2 : 兩條直線 時間限制:10000ms 單點時限:1000ms 內存限制:256MB 描述 平面上N個點,(X1, Y1), (X2, Y2) ... (XN, YN),已知這N個點都在兩條直線y = a1x + b1和y = a2x + b2上(a1 > a2),而且每條直線上至少有10個點。io
請你找出這兩條直線,即計算出a1, b1和a2, b2。
輸入 第一行包含一個整數N。
如下N行每行包含兩個實數Xi和Yi。
20 <= N <= 100
-1000000 <= Xi, Yi <= 1000000
輸出 輸出一行,依次是a1, b1, a2, b2, 保留1位小數。
樣例輸入 20 2.800 23.480 2.100 5.920 4.900 35.240 9.900 63.240 0.800 12.280 6.400 43.640 6.600 44.760 3.400 7.480 7.600 50.360 3.000 24.600 8.000 13.000 4.300 8.560 3.600 27.960 5.500 38.600 8.900 14.080 0.400 3.880 1.800 5.560 4.200 8.440 4.000 8.200 5.400 9.880 樣例輸出 5.6 7.8 1.2 3.4 ###分析 這題就卡你精度問題了 你怎麼判斷出這兩條線呢? 由於最多隻有100暴力枚舉出第一條 第二條就把不是第一條線上的點暴力枚舉就行 而後要求輸出的k1>k2就比較一下吧 ###代碼
#include<bits/stdc++.h> using namespace std; #define ll long long double k1,b1,k2,b2,k3,b3; double x[110],y[110]; bool vis[110]; int n; void firstline(){ for(int i=1;i<n-1;i++) for(int j=i+1;j<n;j++) { k1=(y[j]-y[i])/(x[j]-x[i]),b1=y[j]-k1*x[j]; for(int r=j+1;r<=n;r++) { k2=(y[r]-y[j])/(x[r]-x[j]),b2=y[r]-k2*x[r]; if(k1==k2&&b1==b2) return; } } } void secondline(){ for(int i=1;i<n-1;i++){ if(vis[i]) continue; for(int j=i+1;j<n;j++) { if(vis[j]) continue; k2=(y[j]-y[i])/(x[j]-x[i]),b2=y[j]-k2*x[j]; for(int r=j+1;r<=n;r++) { if(vis[r]) continue; k3=(y[r]-y[j])/(x[r]-x[j]),b3=y[r]-k3*x[r]; if(k3==k2&&b3==b2) return; } } } } int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); //freopen("in.txt","r",stdin); while(cin>>n){ for(int i=1;i<=n;i++) cin>>x[i]>>y[i]; memset(vis,0,sizeof(vis)); firstline(); for(int i=1;i<=n;i++) if(abs(y[i]-k1*x[i]-b1)<1e-9) vis[i]=1; secondline(); if(k1<k2) swap(k1,k2),swap(b1,b2); printf("%.1f %.1f %.1f %.1f\n",k1,b1,k2,b2); } return 0; }
題目3 : 有向圖可達節點 時間限制:50000ms 單點時限:5000ms 內存限制:256MB 描述 給定一個包含N個節點和M條邊的有向圖,其中節點的編號是1~N。請你對全部節點計算,從該節點總共能夠到達多少個節點?(包含該節點自己)
輸入 第一行包含兩個整數N和M。
如下M行每行包含兩個整數u和v,表明一條從u到v的有向邊。
1 <= N <= 10000 0 <= M <= 20000 1 <= u, v <= N
輸出 輸出N行,每行一個整數。其中第i行表明從i號節點出發能夠到達多少節點。
樣例輸入 4 4
1 2 2 3 1 3 3 4 樣例輸出 4 3 2 1 ###分析 就暴力dfs吧,沒什麼了。時間放寬了5s,要是1s還得優化。我還沒寫出優化的 ###代碼
#include<bits/stdc++.h> using namespace std; #define ll long long vector<int> ve[100010]; bool vis[10010]; int dfs(int s){ int ans=0; for(int i=0;i<ve[s].size();i++) if(!vis[ve[s][i]]) { vis[ve[s][i]]=1; ans+=dfs(ve[s][i]); } return ans+1; } int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); //freopen("in.txt","r",stdin); int n,m; cin>>n>>m; int x,y; for(int i=1;i<=m;i++){ cin>>x>>y; ve[x].push_back(y); } for(int i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); vis[i]=1; cout<<dfs(i)<<endl; } return 0; }