2013-2014 Summer Petrozavodsk Camp, Andrew Stankevich Contest 44 (ASC 44)
阿新 • • 發佈:2018-11-01
暑訓最後一場組隊訓練賽,特麼故意的,把別人的WF練習題給我們寫,寫了半天才簽到兩題。靠!
B - Braess's Paradox
題意:有幾個點,每個點到下一個點之間有兩條路。上面一條路的通過時間是 A*K1+B,下面一條通過時間是C*K2+D,要兩條路通過的時間數儘量相同,K1+K2=1(K1,K2是經過的人流量佔總人數的比例)。然後中間的點可以建驛站,如果中間的點不建驛站,就相當於直接從起點到終點,只有兩條路,如果建了驛站,就相當於從起點到驛站,再從驛站到終點。
題解:前兩個直接算出來就行,一個驛站都不建,就相當於兩條路,把所有點上面那條路,ai.bi,加起來就是上面那一條路的A,B,同理,下面一條路就是所有的,ci,di加起來。每個都建就是相當於一個個點走過去,暴力啊,一個點到另一個點的時間,然後全加起來就行了。後面兩個就是求最小通過時間的和最大通過時間,看似很難,其實就是一個很簡單的DP,N^2的複雜度不會超時。首先預處理從起點到當前點的A,B,C,D。然後每個點的時間就是從前面某一個點建驛站的最小值,最大值轉移過來。直接過來上面路的A,B就用兩個字首相減。
#include<iostream> #include<algorithm> #include<cstring> #include<string> #include<vector> #include<cstdio> #include<cstdlib> #include<cmath> #include<queue> #include<map> #include<set> #include<stack> #include<bitset> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<ll,int> P; #define bug printf("*********\n"); #define debug(x) cout<<"["<<x<<"]" <<endl; #define mid (l+r)/2 #define chl 2*k+1 #define chr 2*k+2 #define lson l,mid,chl #define rson mid,r,chr #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)); const long long mod=1e9+7; const int maxn=5e3+5; const int INF=0x7fffffff; const int inf=0x3f3f3f3f; const double eps=1e-8; int n; int a[maxn],b[maxn],c[maxn],d[maxn]; double qza[maxn],qzb[maxn],qzc[maxn],qzd[maxn]; double dp1[maxn],dp2[maxn]; double ans1,ans2,ans3,ans4; int main() { freopen("braess.in","r",stdin); freopen("braess.out","w",stdout); scanf("%d",&n); for(int i=1; i<=n; i++) { scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]); } double A=0,B=0,C=0,D=0; for(int i=1; i<=n; i++) { //第一種結果都不建,A相當於所有點之間的a[i]相加 A+=a[i]; B+=b[i]; C+=c[i]; D+=d[i]; } double k; if(A+C!=0) { k=min(1.0,(D+C-B)/(A+C));//k1最大值不能超過1 ans1=k*A+B; if(k<=0) { //k1最小值不能小於0,如果小於等於0說明所有人都走下面一條路 ans1=C+D; } } else { ans1=min(B,D); //如果AC都等於零,那就直接判斷B,D大小 } ans2=0; for(int i=1; i<=n; i++) { A=a[i]; //所有的點一個個算 B=b[i]; C=c[i]; D=d[i]; double temp; if(A+C!=0) { k=min(1.0,(D+C-B)/(A+C)); temp=k*A+B; if(k<=0) { temp=C+D; } } else { temp=min(B,D); } ans2+=temp; } for(int i=1; i<=n; i++) { //求字首 qza[i]=qza[i-1]+a[i]; qzb[i]=qzb[i-1]+b[i]; qzc[i]=qzc[i-1]+c[i]; qzd[i]=qzd[i-1]+d[i]; dp1[i]=inf; } dp1[0]=0; for(int i=1; i<=n; i++) { for(int j=0; j<i; j++) { A=qza[i]-qza[j]; B=qzb[i]-qzb[j]; //ABCD等於上一個狀態和當前狀態的差值, C=qzc[i]-qzc[j]; D=qzd[i]-qzd[j]; double temp; if(A+C!=0) { k=min(1.0,(D+C-B)/(A+C)); temp=k*A+B; if(k<=0) { temp=C+D; } } else { temp=min(B,D); } dp1[i]=min(dp1[i],dp1[j]+temp); //dp1保留最小值,從j驛站轉移到i驛站的最小值 dp2[i]=max(dp2[i],dp2[j]+temp); //最大值 } } ans3=dp1[n]; ans4=dp2[n]; printf("%.10f\n%.10f\n%.10f\n%.10f\n",ans1,ans2,ans3,ans4); return 0; }
I - Intelligent Tourist
題意:有N場考試,第i考試需要複習pi天,考試時間是di,考試的時間沒法複習,如果沒有複習多天那場考試就不會去,就會去複習其他考試,中間有些天有活動,活動時間是s-t活動時間不會去複習,問最多能通過機場考試。
題解:貪心,這題賊他媽傻逼,漏看了一個條件,DEBUG一個小時。。。,從後面往前面掃,每次選需要複習時間最少的一場考試,因為這個時間只能給後面的所以不用擔心選的考試時間已經過了,至於考試時間不能複習,你直接把考試也當作複習的時間,不去考試就相當於少複習這種科目一天,去了就相當於多複習一天。。。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,int> P;
#define bug printf("*********\n");
#define debug(x) cout<<"["<<x<<"]" <<endl;
#define mid (l+r)/2
#define chl 2*k+1
#define chr 2*k+2
#define lson l,mid,chl
#define rson mid,r,chr
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a));
const long long mod=1e9+7;
const int maxn=1e5+5;
const int INF=0x7fffffff;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
int n,m;
struct one {
ll d,p;
int id;
bool operator<(const one a)const {
return d<a.d;
}
} X;
struct two {
ll st,en;
bool operator<(const two a)const {
return st<a.st;
}
} H;
priority_queue<one> q1;
priority_queue<two> q2;
priority_queue<P,vector<P>,greater<P> >q;
int main() {
freopen("intelligent.in","r",stdin);
freopen("intelligent.out","w",stdout);
while(~scanf("%d",&n)&&n) {
vector<int> v;
for(int i=0; i<n; i++) {
scanf("%I64d%I64d",&X.d,&X.p);
X.p++;
X.id=i+1;
q1.push(X);
}
scanf("%d",&m);
for(int i=0; i<m; i++) {
scanf("%I64d%I64d",&H.st,&H.en);
q2.push(H);
}
while(q2.size()) {
if(q2.top().st>q1.top().d) {
q2.pop();
} else break;
}
while(q1.size()) {
X=q1.top();
q1.pop();
ll temp;
if(q1.size()==0)temp=0;
else temp=q1.top().d;
ll tim=0;
tim=X.d-temp;
while(q2.size()) {
H=q2.top();
if(H.st>temp) {
q2.pop();
tim-=H.en-H.st+1;
} else break;
}
if(X.p==0) {
v.push_back(X.id);
} else q.push(P(X.p,X.id));
while(tim>0&&q.size()) {
P temp2=q.top();
q.pop();
if(tim>=temp2.first) {
tim-=temp2.first;
v.push_back(temp2.second);
} else {
temp2.first-=tim;
tim=0;
q.push(temp2);
}
}
}
while(q1.size())q1.pop();
while(q2.size())q2.pop();
while(q.size())q.pop();
sort(v.begin(),v.end());
int ans=v.size();
printf("%d\n",ans);
for(int i=0; i<ans; i++) {
printf("%d",v[i]);
if(ans==i+1)printf("\n");
else printf(" ");
}
if(ans==0)puts("");
}
return 0;
}