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;
}
原文地址:https://www.cnblogs.com/shenben/p/6058969.html