[清橙A1210]光稜坦克
阿新 • • 發佈:2018-11-12
[清橙A1210]光稜坦克
題目大意:
平面上放置了\(n(n\le7000)\)個反射裝置,光纖將從某個裝置出發,在經過一處裝置時發生反射,若經過的裝置座標依次為\((x_1,y_1),(x_2,y_2),\ldots,(x_k,t_k)\),則必須滿足:
- \(\forall j \in (1,k],y_j< y_{j-1}\)
- \(\forall j\in (2,k],x_{j-2}< x_j < x_{j-1} \vee x_{j-1}< x_j < x_{j-2}\)
兩種光線不同當且僅當經過的折射裝置的集合不同,求總共有多少種合法的光線。
思路:
一個很顯然的\(\mathcal O(n^3)\)的動態規劃是,首先將所有點按照\(y\)排序,\(f_{i,j}\)表示考慮前\(i\)個裝置,最後一個點是\(i\),上一個點的\(x\)是\(j\)的方案數。字首和優化到\(\mathcal O(n^2)\),空間\(\mathcal O(n^2)\)。
然而這題要求空間複雜度是\(\mathcal O(n)\)。
於是就有了下面\(\mathcal O(n)\)空間的新做法。
原始碼:
#include<cstdio> #include<cctype> #include<algorithm> inline int getint() { register char ch; register bool neg=false; while(!isdigit(ch=getchar())) neg|=ch=='-'; register int x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return neg?-x:x; } const int N=7002; struct Point { int x,y; bool operator < (const Point &rhs) const { return x>rhs.x; } }; Point p[N]; int f[N][2]; int main() { const int n=getint(),mod=getint(); for(register int i=1;i<=n;i++) { p[i].x=getint(); p[i].y=getint(); } std::sort(&p[1],&p[n]+1); for(register int i=1;i<=n;i++) { f[i][0]=f[i][1]=1; for(register int j=i-1;j;j--) { if(p[j].y<p[i].y) (f[i][0]+=f[j][1])%=mod; if(p[j].y>p[i].y) (f[j][1]+=f[i][0])%=mod; } } int ans=mod-n; for(register int i=1;i<=n;i++) { (ans+=f[i][0])%=mod; (ans+=f[i][1])%=mod; } printf("%d\n",ans); return 0; }