2016-11-13试题解题报告
2016-11-13试题解题报告
By shenben
本解题报告解析均为100分解题思路。
T1
贪心
对于每个数i,把他的不同的左边与右边统计下来。
那么,对于每个数i的记录的元素b[i]都改b[i]的中位数一定是最优的。
那么我们统计初始代价,sum/2;
统计ans=max(b[i]可以减小的代价)
答案:sum/2-ans
T2
区间dp
f[i][j](i!=j)表示任意位置(i,j)是'(',')'的概率
Dp[i][j]表示两边是(i,j)是'(',')',并且中间是合法序列的概率
dp[i][j]表示区间[i,j]是合法序列的概率
初始化:if(i+1>j-1) dp[i][j]=Dp[i][j]=f[i][j];
else dp[i][j]=Dp[i][j]=dp[i+1][j-1]*f[i][j];
状态转移:dp[i][j]+=Dp[i][k]*dp[k+1][j];
T3
最短路+乘法原理
对于除1外的所有点,处理出cnt[x],表示1->x的最短路的路径条数
ans=(i:2->n)∏cnt[i]
T1代码:
#include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<ctime> #include<iostream> #include<algorithm> #include<vector> #include<queue> #include<stack> #include<map> #define R register #define ll long long #ifdef unix #define LL "%lld" #else #define LL "%I64d" #endif #define debug(x) cout<<x<<"----"<<endl using namespace std; inline int read(){ R int x=0;bool f=1; R char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=0;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return f?x:-x; } inline char in(){ for(R char ch=getchar();;ch=getchar()) if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) return ch; } const int N=1e5+10; int n,m,a[N]; vector<int>b[N]; #define name "note" int main(){ freopen(name".in","r",stdin); freopen(name".out","w",stdout); n=read();m=read(); for(int i=1;i<=m;i++) a[i]=read(); for(int i=2;i<=m;i++) if(a[i-1]!=a[i]) b[a[i-1]].push_back(a[i]); for(int i=1;i<m;i++) if(a[i+1]!=a[i]) b[a[i+1]].push_back(a[i]); ll ans=0,sum=0; for(int i=1,s;i<=n;i++){ if(!b[i].size()) continue; sort(b[i].begin(),b[i].end()); ll before=0,after=0; ll y=b[i][b[i].size()>>1]; for(int j=0;j<b[i].size();j++){ before+=(ll)abs(i-b[i][j]); after+=(ll)abs(y-b[i][j]); } ans=max(ans,before-after); sum+=before; } printf(LL,sum/2-ans); fclose(stdin); fclose(stdout); return 0; } /*25分存档 const int N=1e5+10; const int inf=0x7fffffff; int n,m,cnf,a[N],b[N]; struct node{ int v,x; }f[N],bf[N]; int zmx,p,ans; int pos[110]; bool vis[110]; inline int ABS(int x){ return x>0?x:-x; } void go(){ int maxx=0,minx=inf;ans=inf; for(int i=1;i<=m;i++) maxx=max(maxx,a[i]),minx=min(minx,a[i]),vis[a[i]]=1; for(int i=minx;i<=maxx;i++){ if(!vis[i]) continue; memcpy(b,a,sizeof a); pos[0]=0; for(int j=1;j<=m;j++){ if(b[j]==i) pos[++pos[0]]=j; } for(int k=minx;k<=maxx;k++){ if(k==i) continue; int tmp=0; for(int l=1;l<=pos[0];l++) b[pos[l]]=k; for(int l=1;l<m;l++) tmp+=ABS(b[l+1]-b[l]); ans=min(ans,tmp); } } printf("%d",ans); } #define name "note" int main(){ freopen(name".in","r",stdin); freopen(name".out","w",stdout); n=read();m=read(); for(int i=1;i<=m;i++) a[i]=read(); if(n<=100&&m<=100){go();return 0;} f[cnf=1].v=a[1];f[1].x=1; for(int i=2;i<=m;i++){ if(a[i]==f[cnf].v) f[cnf].x++; else{ f[++cnf].v=a[i];f[cnf].x=1; } } for(int i=1;i<=cnf;i+=2) if(f[i].v==f[i+2].v){ if(f[i].x+f[i+2].x>zmx){ zmx=f[i].x+f[i+2].x; p=i; } } for(int i=2;i<=cnf;i+=2) if(f[i].v==f[i+2].v){ if(f[i].x+f[i+2].x>zmx){ zmx=f[i].x+f[i+2].x; p=i; } } for(int i=1;i<m;i++) ans+=ABS(a[i+1]-a[i]); if(p){ int xg=f[p].v; p++; int tmp=f[p].v; for(int i=1;i<=m;i++) if(f[i].v==tmp) f[i].v=xg; int temp=0; for(int i=1;i<p;i++) temp+=ABS(f[i+1].v-f[i].v); for(int i=p+1;i<m;i++) temp+=ABS(f[i+1].v-f[i].v); ans=min(ans,temp); } for(int i=1,t;i<cnf;i++) if((t=ABS(f[i].v-f[i+1].v))>zmx){ zmx=t;p=i; } memcpy(bf,f,sizeof f); int tmp1=bf[p].v; int tmp2=bf[p+1].v; int temp=0; for(int i=1;i<=cnf;i++) if(bf[i].v==tmp1) bf[i].v=tmp2; for(int i=1;i<cnf;i++) temp+=ABS(bf[i+1].v-bf[i].v); ans=min(ans,temp); memcpy(bf,f,sizeof f); temp=0; for(int i=1;i<=cnf;i++) if(bf[i].v==tmp2) bf[i].v=tmp1; for(int i=1;i<cnf;i++) temp+=ABS(bf[i+1].v-bf[i].v); ans=min(ans,temp); printf("%d",ans); fclose(stdin); fclose(stdout); return 0; }*/
T2代码:
#include<cstdio> using namespace std; const int N=201; int n,w; double l[N][N],r[N][N]; double f[N][N],Dp[N][N],dp[N][N]; #define name "brackets" int main(){ freopen(name".in","r",stdin); freopen(name".out","w",stdout); scanf("%d%d",&n,&w); for(int i=1;i<=n;i++){ for(int j=1;j<=w;j++){ scanf("%lf%lf",&l[i][j],&r[i][j]); } } for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ for(int k=1;k<=w;k++){ f[i][j]+=l[i][k]*r[j][k]; } } } //Dp[][]必须要有,因为他是判重的 for(int i=n;i;i--){ for(int j=i+1;j<=n;j++){ //( A ) if(i+1>j-1) dp[i][j]=Dp[i][j]=f[i][j]; else dp[i][j]=Dp[i][j]=dp[i+1][j-1]*f[i][j]; //(A)合并(B) for(int k=i+1;k<j;k++) dp[i][j]+=Dp[i][k]*dp[k+1][j]; } } printf("%.5lf",dp[1][n]); fclose(stdin); fclose(stdout); return 0; } /* 15分 乱搞代码不存了 */
T3代码:
/* 检验最短路径条数时,手残的打了个松弛,WA了8个点。长记性了。 */ #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<ctime> #include<iostream> #include<algorithm> #include<vector> #include<queue> #include<stack> #include<map> #define R register #define ll long long #define DB double #define pir pair<int,int> #ifdef unix #define LL "%lld" #else #define LL "%I64d" #endif #define debug(x) cout<<x<<"----"<<endl using namespace std; inline int read(){ R int x=0;bool f=1; R char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=0;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return f?x:-x; } inline char in(){ for(R char ch=getchar();;ch=getchar()) if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) return ch; } const int N=1e5+10; const int M=1e6+10; struct ss{ int u,v,w; bool operator <(const ss &a)const{ return w<a.w; } }ed[M]; struct node{ int v,w,next; }e[M*2]; int n,m,tot,head[N],dis[N]; ll ans=1,cnt[N]; const ll mod=(1LL<<31)-1; bool vis[N]; void add(int x,int y,int z){ e[++tot].v=y; e[tot].w=z; e[tot].next=head[x]; head[x]=tot; } const int inf=2e9; inline void dijkstra(){ priority_queue<pir,vector<pir>,greater<pir> >q; for(int i=1;i<=n;i++) dis[i]=inf; dis[1]=0; q.push(make_pair(0,1)); while(!q.empty()){ pir t=q.top();q.pop(); int x=t.second; if(vis[x]) continue; vis[x]=1; for(int i=head[x];i;i=e[i].next){ int v=e[i].v,w=e[i].w; if(!vis[v]&&dis[v]>dis[x]+w){ dis[v]=dis[x]+w; q.push(make_pair(dis[v],v)); } } } } int q[N<<1]={0}; const int QLEN=N*2-5; inline void spfa(){ memset(vis,0,sizeof vis); int h=0,t=1; dis[1]=0; vis[1]=1; q[t]=1; while(h<t){ if(++h>QLEN) h=1; int x=q[h]; //vis[x]=0;//单纯检验最短路,(不更新),不需要松弛 for(int i=head[x];i;i=e[i].next){ int v=e[i].v,w=e[i].w; if(dis[v]==dis[x]+w){ if(++cnt[v]>=mod) cnt[v]-=mod; if(!vis[v]){ vis[v]=1; if(++t>QLEN) t=1; q[t]=v; } } } } } #define name "castle" int main(){ freopen(name".in","r",stdin); freopen(name".out","w",stdout); n=read();m=read(); for(int i=1;i<=m;i++) ed[i].u=read(),ed[i].v=read(),ed[i].w=read(); sort(ed+1,ed+m+1); for(int i=1;i<=m;i++){ add(ed[i].u,ed[i].v,ed[i].w); add(ed[i].v,ed[i].u,ed[i].w); } dijkstra(); for(int i=1;i<=n;i++) if(dis[i]==inf){puts("0");return 0;} if(n-1==m){puts("1");return 0;} spfa(); for(int i=2;i<=n;i++) ans=(ans*cnt[i])%mod; printf(LL,ans); fclose(stdin); fclose(stdout); return 0; }