NOIP2018普及組解題報告
阿新 • • 發佈:2018-12-16
解題報告
洛谷 5015 標題統計
程式碼(題目過水)
#include <cstdio>
#include <cctype>
using namespace std;
int ans; char c;
int main(){
while ((c=getchar())!=EOF) ans+=isalnum(c)>0;
return !printf("%d",ans);
}
洛谷 5016 龍虎鬥
分析
有許多偽蒟蒻都漏掉了m號的情況,結果可能就與一等獎失之交臂,思路就是對於每一個節點判斷最小值。(我朋友竟然打了二分,與一等獎失之交臂,當然,這是後話)
程式碼
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
typedef long long bnt;
const int N=100010;
int n,m,choi,a[N+1],ans; bnt ans1,ans2,sum;
inline int iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
return ans;
}
int main(){
n=iut(); for (rr int i=1;i<=n;++i) a[i]=iut();
m=iut(); rr int x=iut(); a[x]+=iut(); choi=iut();
for (rr bnt i=1;i<m;++i) ans1+=(m-i)*a[i];
for (rr bnt i=m+1;i<=n;++i) ans2+=(i-m)*a[i];
ans=m; sum=ans1<ans2?ans2-ans1:ans1-ans2;//m號初始化
for (rr bnt i=1;i<m;++i){//軒軒
ans1+=(m-i)*choi;
rr bnt t=ans1<ans2?ans2-ans1:ans1-ans2;
if (t<sum) sum=t,ans=i;
ans1-=(m-i)*choi;
}
for (rr bnt i=m+1;i<=n;++i){//凱凱
ans2+=(i-m)*choi;
rr bnt t=ans1<ans2?ans2-ans1:ans1-ans2;
if (t<sum) sum=t,ans=i;
ans2-=(i-m)*choi;
}
printf("%d",ans);
return 0;
}
洛谷 5017 擺渡車
分析(線性dp)
作為這套題最難的一道題,我差點悲劇,不過這道題是一道dp的題目,設
表示第
個同學(排序後)等車
分鐘後的最短等待時間,那麼在同一段的時候
要新開一段的時候
直到現在,時間複雜度已經是
,已經比較高效了,但是按照dalao的思路,可以用字首最小值優化
的時間,優化至
程式碼(線性dp)
#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
#define min(a,b) (((a)<(b))?(a):(b))
using namespace std;
int dp[2][201],ans=1e8,n,m,a[501];
inline int iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
return ans;
}
int main(){
n=iut(); m=iut();
for (rr int i=1;i<=n;++i) a[i]=iut();
sort(a+1,a+1+n);
for (rr int i=1;i<=n;++i){
dp[i&1][0]=1e8;
for (rr int j=0;j<=min(a[i]-a[i-1]-m,m-1);++j) dp[i&1][0]=min(dp[i&1][0],dp[1-(i&1)][j]);
for (rr int j=1;j<2*m;++j){
dp[i&1][j]=dp[i&1][j-1];//字首最小值
if (a[i]-a[i-1]+j>=m&&a[i]-a[i-1]+j<3*m)
dp[i&1][j]=min(dp[i&1][j],dp[1-(i&1)][a[i]-a[i-1]+j-m]);//新開一段
}
for (rr int j=0;j+a[i]-a[i-1]<2*m;++j)
dp[i&1][j]=min(dp[i&1][j],dp[1-(i&1)][j+a[i]-a[i-1]]);//同一段
for (rr int j=0;j<2*m;++j) dp[i&1][j]+=j;//無論開不開都要加等待時間
}
for (rr int i=0;i<m;++i) ans=min(ans,dp[n&1][i]);//取最小值
return !printf("%d",ans);
}
分析(斜率優化)
斜率優化與上面的線性dp迥然不同,而且對於
這麼小的情況下,
太大了,不過為了培養更多的思維,在此講一下斜率優化的方法(肯定非高效正解)
設
表示到第
時刻的總等待時間,
表示到第
時刻的同學個數,
表示在第
時刻時才發車的總等待時間
那麼
然而這樣肯定會超時,若使
更優秀,那麼