German Collegiate Programming Contest 2018 7.19(計蒜客)
阿新 • • 發佈:2019-02-06
C. Coolest Ski Route
題意:求一個有向圖中的最長路
題解:一開始是沒這麼多想,直接用dfs和bfs試了下,從圖中入度為0的結點開始搜尋,然後超時,後來明白要用到記憶化搜尋,記錄每個點的搜尋距離,當下次搜到某個已經搜過的點時不必繼續下去,用儲存的結果
超時程式碼:
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <vector> #include <queue> #define maxn 1005 #define INF 0x3f3f3f3f #define LL long long using namespace std; struct node { int to,w; }; struct knode { int d,sz; }; vector<node>v[maxn]; bool book[maxn],vis[maxn]; int n,m,a,b,c,sum,maxi,ans; void dfs(int e) { if(!v[e].size()) { if(sum>maxi) maxi=sum; return ; } for(int i=0;i<v[e].size();i++) { if(vis[v[e][i].to]==false) { vis[v[e][i].to]=true; sum+=v[e][i].w; dfs(v[e][i].to); vis[v[e][i].to]=false; sum-=v[e][i].w; } } } void bfs(int e) { queue<knode>q; knode h,t; h.d=e;h.sz=0; q.push(h); memset(vis,false,sizeof(vis)); vis[e]=true; while(!q.empty()) { knode h=q.front(); q.pop(); for(int i=0;i<v[h.d].size();i++) { if(vis[v[h.d][i].to]==false) { //vis[v[h.d][i].to]=true; t.d=v[h.d][i].to; t.sz=v[h.d][i].w+h.sz; //cout << t.d << ' '; //cout << t.sz <<endl; q.push(t); if(!v[t.d].size()) { if(t.sz>maxi) maxi=t.sz; } } } } } int main() { ios::sync_with_stdio(false); cin>>n>>m; for(int i=0;i<m;i++) { cin>>a>>b>>c; node t; t.to=b;t.w=c; v[a].push_back(t); book[b]=true; } /*for(int i=1;i<=n;i++) { if(book[i]==false) { memset(vis,false,sizeof(vis)); maxi=-1;sum=0; dfs(i); } ans=max(ans,maxi); } cout << ans << endl;*/ for(int i=1;i<=n;i++) { if(book[i]==false) { //cout << i <<endl; memset(vis,false,sizeof(vis)); maxi=-1; bfs(i); } ans=max(ans,maxi); } cout << ans << endl; return 0; }
AC程式碼:
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #define maxn 1005 #define inf 0x3f3f3f3f #include <cstring> #include <vector> #define LL long long using namespace std; int dp[maxn]; struct node { int to,w; }; vector<node>v[maxn]; bool book[maxn],vis[maxn]; int n,m,a,b,c,sum,maxi,ans; int rec(int e) { if(vis[e]) return dp[e]; for(int i=0;i<v[e].size();i++) { dp[e]=max(dp[e],rec(v[e][i].to)+v[e][i].w); } vis[e]=true; return dp[e]; } int main() { cin>>n>>m; for(int i=0;i<m;i++) { cin>>a>>b>>c; node t; t.to=b;t.w=c; v[a].push_back(t); book[b]=true; } for(int i=1;i<=n;i++) { if(book[i]==false) { ans=max(ans,rec(i)); } } cout << ans << endl; return 0; }
D. Down the Pyramid
題意:數塔,給出一行n個數字,確定第二行n+1個數字滿足t[i]=a[i-1]-t[i-1]的方案數
題解:一開始是想到是先找到最小的值下標minp,讓t[minp]等於0開始列舉到a[minp],t[minp]每增加1,其t[minp+2*k-1]就減小1,直到t[minp+2*k-1]的最小值減到0,累加次數,這種解法wrong。 後來看了官方題解,直接讓t[0]賦值0,記錄
low=max(low,-t[2*k]),high=min(high,t[2*k+1]),ans=max(0ll,high-low+1)
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<time.h> #include<iostream> #include<algorithm> #include <set> #include <functional> #include <map> #include <vector> using namespace std; #define maxn 1000005 #define INF 0x3f3f3f3f typedef long long LL; LL n,a[maxn],t[maxn]; int main() { cin>>n; for(int i=0;i<n;i++) { cin>>a[i]; } t[0]=0; for(int i=1;i<=n;i++) { t[i]=a[i-1]-t[i-1]; } LL l,h; l=0;h=INF; for(int i=0;i<=n;i+=2) { l=max(l,-t[i]); } for(int i=1;i<=n;i+=2) { h=min(h,t[i]); } cout << max(0ll,h-l+1) << endl; return 0; }
H. Hyper Illuminati
題意:給定一個數m,求最小的n,s滿足 1^(n-1)+2^(n-1)+3^(n-1)+...+s^(n-1)=m
題解:因為m最大為10^16,2^60>10^16,n可從3到60迴圈列舉,對每一個n,看是否有滿足條件的s
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define maxn 1005
#define inf 0x3f3f3f3f
#include <cstring>
#include <vector>
#define LL long long
using namespace std;
LL m;
int main()
{
cin>>m;
for(int i=3;i<=60;i++)
{
int bz=0;
LL t=1;
LL sum=0;
while(sum<m)
{
bz++;
t=1;
for(int j=1;j<i;j++)
{
t*=bz;
}
sum+=t;
}
//cout << sum << endl;
if(sum==m)
{
cout << i << ' ' << bz << endl;
return 0;
}
}
cout << "impossible\n";
return 0;
}