1. 程式人生 > >洛谷 P2315 [HNOI2005]數三角形 暴力

洛谷 P2315 [HNOI2005]數三角形 暴力

題目描述 這裡寫圖片描述 輸入輸出格式

輸入格式: 這裡寫圖片描述

輸出格式: 輸出檔案output.txt中僅包含一個整數T,表示有多少個三角形的邊界都沒有被刪除。

輸入輸出樣例

輸入樣例#1: 5 1 1 1 1 1 0 1 1 0 1 1 1 1 1 1 1 0 1 1 0 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 輸出樣例#1: 19

分析: 我們維護每個點往左上(lu),左下(ld),右上(ru),右下(rd),往左(l)最多能走多少步。 然後我們列舉每個點為正立的三角形的右下角,顯然這個三角形最大邊長是

min(lu[i][j],l[i][j])。 我們列舉這個長度k,顯然另一個頂點為(i,jk),然後判斷ru[i][jk]是否大於k。 這樣做是O(n3)的,但是由於資料水,是能過的。 至於考慮優化,也就是要滿足,

ru[i][jk]>=k 也就是要查詢一個區間[jmaxk][j1]的大於k的數的個數,這個可以用可持久化權值線段樹做。 複雜度是O(n2logn)的,但是不想打。

程式碼:

#include <iostream>
#include <cmath> #include <cstdio> const int maxn=1007; using namespace std; int n,x,y,z,ans; int lu[maxn][maxn],ru[maxn][maxn],ld[maxn][maxn],rd[maxn][maxn]; struct rec{ int l,r,d; }h[maxn][maxn]; int main() { scanf("%d",&n); for (int i=1;i<=n;i++) { for (int j=1;j<=i;j++)
{ scanf("%d%d%d",&h[i][j].l,&h[i][j].r,&h[i][j].d); } } for (int i=1;i<=n;i++) { for (int j=1;j<=i;j++) { if (h[i][j].l) ru[i+1][j]=ru[i][j]+1; if (h[i][j].r) lu[i+1][j+1]=lu[i][j]+1; } } for (int i=n;i>0;i--) { for (int j=i;j>0;j--) { if (h[i][j].l) ld[i][j]=ld[i+1][j]+1; if (h[i][j].r) rd[i][j]=rd[i+1][j+1]+1; } } for (int i=1;i<=n+1;i++) { for (int j=1;j<=i;j++) { for (int k=j-1;(k>0) && (h[i-1][k].d) && (j-k<=lu[i][j]);k--) { ans+=(j-k)<=ru[i][k]; } for (int k=j-1;(k>0) && (h[i-1][k].d) && (j-k<=ld[i][j]);k--) { ans+=(j-k)<=rd[i][k]; } } } printf("%d",ans); }