codeforces 597

D题

在一个二维平面上面,有n个城市,现在每个城市都没有电。

你可以选择一些城市建发电站,代价是c[i];你也可以给每个城市拉电线,给城市(i,j)之间拉电线的代价是(abs(x[i]-x[j])+abs(y[i]-y[j]))*(k[i]+k[j])。

现在问你最少花费多少代价,能够使得全部城市都有电,输出方案。

题解

建立一个超级源点,每个城市与超级源点连边,权重为第i个城市建设发电站的代价

问题就转化为普通最小生成树问题

prim kruskal都可以

注意保留下路径

与0节点相连的都是自建发电站

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define sc(x) scanf("%I64d",&x);
#define si signed
#define fi first
#define se second
#define pb push_back
#define forn for(int i=0;i<n;i++)
int n;
#define P pair<int,int>
P A[2005];
int C[2005];
int K[2005];

int d[2005];
bool vis[2005];
int mp[2005][2005];
int pre[2005];
vector<int>v;
vector<P> vv;

void prim()
{
   // vis[0]=1;
    for(int i=1; i<=n; i++)
    {
        d[i]=1e18;
    }
    d[0]=0;
    for(int i=0; i<=n; i++)
    {
        int x=-1;
        for(int j=0; j<=n; j++)
            if(!vis[j]&&(x==-1||d[j]<d[x]))x=j;
        if(x==-1)break;
        vis[x]=1;
        for(int j=0; j<=n; j++)
        {
            if(!vis[j]){
               if(d[j]>mp[x][j]){pre[j]=x;d[j]=mp[x][j];}
            }
        }
    }
}
si main()
{
    sc(n)
    for(int i=1; i<=n; i++)
    {
        sc(A[i].fi)
        sc(A[i].se)
    }
    for(int i=1; i<=n; i++)
    {
        sc(C[i])
        mp[i][0]=mp[0][i]=C[i];
    }
    for(int i=1; i<=n; i++)sc(K[i]);
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            mp[i][j]=(K[i]+K[j])*((labs(A[i].fi-A[j].fi))+(labs(A[i].se-A[j].se)));
        }
    }
    prim();
    int ans=0;
    for(int i=0; i<=n; i++)
    {
        ans+=d[i];
    }
    cout<<ans<<'\n';
    memset(vis,0,sizeof vis);vis[0]=1;
    for(int i=1;i<=n;i++){
        if(pre[i]==0){
            v.push_back(i);
            vis[i]=1;
        }
    }
    cout<<v.size()<<endl;
    for(int i=0;i<v.size();i++)cout<<v[i]<<' ';
    cout<<endl;
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            vv.push_back(P(i,pre[i]));
            vis[i]=1;
        }
    }
    cout<<vv.size()<<endl;
    for(int i=0;i<vv.size();i++)cout<<vv[i].fi<<' '<<vv[i].se<<endl;
}

  C

简单dp,字符串中他会把源字符串的w翻译成uu,把m变成nn,现在给你一个字符串问他的源字符串有多少种

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define sc(x) scanf("%I64d",&x);
#define si signed
#define fi first
#define se second
#define pb push_back
#define forn for(int i=0;i<n;i++)
char s[100005];
const int mod= 1e9+7;
int dp[100005];
void init()
{
    dp[0]=dp[1]=1;
    for(int i=2;i<=100000;i++){
        dp[i]=(dp[i-1]+dp[i-2])%mod;
    }
}
si main()
{
    init();
    scanf("%s",s+1);
    int n=strlen(s+1);
    int ans=1;
    for(int i=1;i<=n;){
        if(s[i]=='w'||s[i]=='m'){
            puts("0");
            return 0;
        }
        if(s[i]=='u'){
            int k=0;
            while(i<=n){
                if(s[i]=='u')k++,i++;
                else break;
            }
            ans=(ans*dp[k])%mod;
        }else if(s[i]=='n'){
            int k=0;
            while(i<=n){
                if(s[i]=='n')k++,i++;
                else break;
            }
            ans=(ans*dp[k])%mod;
        }else i++;
    }
    cout<<ans<<'\n';
 
}

  E

期望dp

现在有一个10*10的矩阵,玩家要从左下角走到左上角,会先往右边走,再往左边走,再往右边走(看NOTE里面的图),然后这个图里面有一些梯子,用梯子可以爬到上面去。

现在这个人在掷骰子,问你期望最少花费多少次,能够到达终点。

如果你到终点前,你的骰子超过了终点,那么将不会移动。

首先dp【i】表示走到第i步的最小期望,由于在终点附件那里如果步数超过,那只能原地走

dp【1】=1//6*(dp0+1)+5/6(dp1+1)

dp【2】=1/6*(dp0+1)+1/6*(dp1+1)+2/3*(dp2+1)

由于dp0=0;

故dp1至dp5可求出来是6;

接下来的每个点就是,先不考虑地图的梯子,先考虑转移

就是dp【i】+=sigma(j=1~6)【(1/6)*d[i-j]】

当有梯子时,直接考虑要不要用梯子就行,取min最小值

 

#include<bits/stdc++.h>
using namespace std;
const int maxn = 15;
double dp[maxn*maxn];
int idx[maxn][maxn];
int ladders[maxn*maxn];
int main(){
    for(int i=0;i<10;i++){
        for(int j=0;j<10;j++){
            if(i%2){
                idx[i][j]=(i*10+9-j);
            }else{
                idx[i][j]=(i*10+j);
            }
        }
    }
//        for(int i=0;i<10;i++){
//        for(int j=0;j<10;j++){
//            cout<<idx[i][j]<<' ';
//        }
//        puts("");
//        }
    for(int i=0;i<10;i++){
        for(int j=0;j<10;j++){
            int x;scanf("%d",&x);
            ladders[idx[i][j]]=idx[i-x][j];
        }
    }
    for(int i=0;i<10;i++){
        for(int j=0;j<10;j++){
            cout<<ladders[idx[i][j]]<<' ';
        }
        puts("");
    }
    dp[0]=0;
    for(int i=1;i<6;i++)
        dp[i]=6;
    for(int i=6;i<100;i++){
        double sum = 0;
        for(int step=1;step<=6;step++){
            sum = sum + min(dp[i-step],dp[ladders[i-step]]);
        }
        dp[i]=(sum/6)+1;
    }
    cout<< setprecision(10) << dp[99] << endl;
}

  

posted on 2020-02-18 16:22  师姐的迷弟  阅读(154)  评论(0编辑  收藏  举报

导航