标签:
题意:一个环形跑道,每到一个站可以获得汽油,每到下一个站消耗一定的汽油,问标号最小的使得能够完成一次环形的起点站。
题解:如果朴素的枚举起点,复杂度达到O(N*N*T)超时。所以考虑是否当前所肯定或者否定的起点给可以对下一次进行排除或化简,或者也可能是具有特殊性质,不需要进行一次完整的遍历计算,也就是分别从第一个T和第二个T两个角度去考虑。发现如果当前起点不可行,那么起点到最远可以到达的点之间所有的点都不可以作为起点。完成优化。
//debug:值得注意的就是环状的怎么写
代码:
#include <cstdio> #include <cmath> #include <cstring> #include <iostream> #include <algorithm> #include <set> #include <vector> #include <queue> #include <map> #include <stack> using namespace std; #define test freopen("in.txt","r",stdin) #define pt(s,p) cout<<s<<"="<<p<<endl; #define ptp(s1,p1,s2,p2) cout<<s1<<"="<<p1<<","<<s2<<"="<<p2<<endl; #define pb(u) push_back(u) #define ptln cout<<endl; #define ptarr(i,a,s,f) for(int i=s;i<=f;i++) {if(i!=f) cout<<a[i]<<" ";else cout<<a[i]<<endl;} #define REP(i,s,f) for(int i=s;i<=f;i++) #define RREP(i,s,f) for(int i=s;i>=f;i--) #define CL(a,v) memset(a,v,sizeof(a)) #define IOS ios_base::sync_with_stdio() const int maxn=100001+1000; int p[maxn],q[maxn]; int bad[maxn]; int main() { int T,N; cin>>T; REP(kase,1,T) { cin>>N; CL(bad,0); REP(i,0,N-1) cin>>p[i]; REP(i,0,N-1) cin>>q[i]; int flg=0; int ans=0; REP(a,0,N-1) { if(bad[a]) continue; int remain=0; int maxi=-1; REP(i,1,N) { int pqptr=(a+i-1)%N; remain=remain+p[pqptr]-q[pqptr]; if(remain<0) break; else maxi=i; } // ptp("a",a,"maxi",maxi); if(maxi==N) { ans=a; flg=1; break; } else if(maxi==-1) bad[a]=1; else { for(int j=a;j!=(a+maxi-1)%N;j=(j+1)%N) bad[j]=1; } } printf("Case %d: ",kase); if(flg) printf("Possible from station %d\n",ans+1); else printf("Not possible\n"); } return 0; }
标签:
原文地址:http://www.cnblogs.com/diang/p/4858007.html