7.16 集訓總結
阿新 • • 發佈:2020-07-16
A、Layout
題目描述
分析
裸的差分約束,細節比較多
程式碼
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+5; typedef long long ll; int head[maxn],tot=1,n,m,k; struct asd{ int from,to,next; ll val; }b[maxn]; void ad(int aa,int bb,ll cc){ b[tot].from=aa; b[tot].to=bb; b[tot].val=cc; b[tot].next=head[aa]; head[aa]=tot++; } ll dis[maxn]; bool vis[maxn]; queue<int> q; int init[maxn]; ll spfa(int xx){ memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); memset(init,0,sizeof(init)); dis[xx]=0; q.push(xx); while(!q.empty()){ int now=q.front(); q.pop(); vis[now]=0; for(int i=head[now];i!=-1;i=b[i].next){ int u=b[i].to; if(dis[u]>dis[now]+b[i].val){ dis[u]=dis[now]+b[i].val; if(vis[u]==0){ q.push(u); vis[u]=1; init[u]++; if(init[u]>n){ return -1; } } } } } if(dis[n]==0x3f3f3f3f3f3f3f3f) return -2; return dis[n]; } int main(){ memset(head,-1,sizeof(head)); scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=m;i++){ int aa,bb; ll cc; scanf("%d%d%lld",&aa,&bb,&cc); if(aa<bb){ ad(aa,bb,cc); } else { ad(bb,aa,cc); } } for(int i=1;i<=k;i++){ int aa,bb; ll cc; scanf("%d%d%lld",&aa,&bb,&cc); if(aa>bb){ ad(aa,bb,-cc); } else { ad(bb,aa,-cc); } } for(int i=1;i<n;i++){ ad(i+1,i,0); } for(int i=1;i<=n;i++){ ad(0,i,0); } if(spfa(0)==-1){ printf("-1\n"); return 0; } printf("%lld\n",spfa(1)); return 0; }
B、遊戲
題目描述
分析
用並差集倒序列舉
程式碼
#include<bits/stdc++.h> using namespace std; const int maxn=5e5+5; int f[maxn],ff[maxn],a[maxn][2],n; int zhao(int xx,int tim){ if(tim>n) return f[xx]=0; if(xx==f[xx]) return xx; return f[xx]=zhao(f[xx],tim+1); } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) f[i]=i; for(int i=1;i<=n;i++){ int aa; scanf("%d",&aa); if(aa!=0) f[i]=ff[i]=aa; } int q; scanf("%d",&q); for(int i=1;i<=q;i++){ scanf("%d%d",&a[i][0],&a[i][1]); if(a[i][0]==2) f[a[i][1]]=a[i][1]; } for(int i=q;i>=1;i--){ if(a[i][0]==1) a[i][1]=zhao(a[i][1],0); else f[a[i][1]]=ff[a[i][1]]; } for(int i=1;i<=q;i++){ if(a[i][0]==1){ if(a[i][1]) printf("%d\n",a[i][1]); else printf("CIKLUS\n"); } } return 0; }
C、數字
題目描述
分析
計數類DP
程式碼
#include <bits/stdc++.h> typedef long long ll; const int maxn=1e3+5; const ll mod=999983; ll n,a[maxn],dp[maxn][9*maxn],len; char s[maxn]; int main() { scanf("%lld%s",&n,s+1); len=strlen(s+1); for(ll i=1;i<=len;++i){ a[i]=s[i]-'0'; } dp[0][0]=1; for(ll i=1;i<=n;++i){ for(ll j=0;j<=i*9;j++){ for(ll k=1;k<=len;k++){ if(j>=a[k]) dp[i][j]=(dp[i][j]+dp[i-1][j-a[k]])%mod; } } } ll ans=0; for(ll i=0;i<=n*9;i++){ ans=(ans+2*dp[n][i]*dp[n][i])%mod; } ll len1=(n+1)/2,len2=n/2,ans1=0,ans2=0; for(ll i=0;i<=len1*9;i++){ ans1=(ans1+dp[len1][i]*dp[len1][i]%mod)%mod; } for(ll i=0;i<=len2*9;i++){ ans2=(ans2+dp[len2][i]*dp[len2][i]%mod)%mod; } ans=(ans-ans1*ans2%mod+mod)%mod; printf("%lld\n",ans); return 0; }
D、水站
題目描述
分析
玄學剪枝+暴力列舉
程式碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=150505;
ll yy[maxn],xz[maxn],hf[maxn],ans,n;
vector<ll> da;
vector<ll> jl;
void solve(ll now){
jl.clear();
ll head=now,dys=yy[now],tot=hf[now],cs;
jl.push_back(now);
while(head<=n){
cs=yy[++head]+dys;
if(cs>xz[head]){
dys=cs;
} else {
dys=cs;
tot+=hf[head];
jl.push_back(head);
}
if(tot>=ans) return;
}
if(tot<ans){
ans=tot;
da.clear();
for(int i=0;i<jl.size();i++){
da.push_back(jl[i]);
}
}
}
int main(){
scanf("%lld",&n);
for(ll i=1;i<=n;i++){
scanf("%lld%lld%lld",&yy[i],&xz[i],&hf[i]);
}
ans=hf[n];
da.push_back(n);
for(ll i=1;i<n;i++){
solve(i);
}
printf("%lld\n",ans);
for(int i=0;i<da.size();i++){
if(i==0) printf("%lld",da[i]);
else printf(" %lld",da[i]);
}
printf("\n");
return 0;
}