Codeforces Round #302 (Div. 2)——A.B.C.D.E

http://codeforces.com/contest/544

A. Set of Strings
把一个串分成n个子串,要求这几个子串的第一个字母互不相同

#include <bits/stdc++.h>
using namespace std;
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.cpp","r",stdin);
#endif // ONLINE_JUDGE
    int n;
    cin>>n;
    string s;
    cin>>s;
    int cnt=1;
    string a[28];
    bool vis[28]={0};
    int l=s.length();
    a[1]+=s[0];
    vis[s[0]-'a']=1;
    for(int i=1;i<l;++i){
        if(s[i]!=s[i-1]&&cnt<n&&!vis[s[i]-'a']){
            vis[s[i]-'a']=1;
            a[++cnt]+=s[i];
        }else{
            a[cnt]+=s[i];
        }
    }
    if(cnt<n) puts("NO");
    else{
        puts("YES");
        for(int i=1;i<=n;++i){
            cout<<a[i]<<endl;
        }
    }
    return 0;
}

B. Sea and Islands
S表示水,L表示沙子
在一个n*n的地图上填充m个小岛,输出一种合法解

注意奇数的情况,最多可以填充(n*n+1)/2个小岛

#include <bits/stdc++.h>
const int MAXN = 110;
using namespace std;
char mp[MAXN][MAXN];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.cpp","r",stdin);
#endif // ONLINE_JUDGE
    int n,m;
    scanf("%d%d",&n,&m);
    if(m> ((n&1)? (n*n+1)/2 :(n*n/2) ) ) puts("NO");
    else{
        puts("YES");
        int k=0;
        for(int i=0;i<n;++i){
            for(int j=0;j<n;++j){
                if((i+j)%2==0&&k<m){
                    mp[i][j]='L';
                    k++;
                }else{
                    mp[i][j]='S';
                }
            }
        }
        for(int i=0;i<n;++i){
            printf("%s\n",mp[i]);
        }
    }
    return 0;
}

C. Writing Code
n个程序猿一起完成m段代码,每个程序猿写一行代码产生的bug数为ai,求为使总bug数为b的方案数,程序猿敲代码必须是按顺序的

完全背包dp[j][k] 表示前j行代码产生k个bug的方案数,用LL

#include <bits/stdc++.h>
typedef long long LL;
const int MAXN = 510;
using namespace std;
int a[MAXN];
int n,m,b,mod;
LL dp[MAXN][MAXN];
int main()
{
    scanf("%d%d%d%d",&n,&m,&b,&mod);
    for(int i=0;i<n;++i){
        scanf("%d",&a[i]);
    }
    dp[0][0]=1;
    for(int i=0;i<n;++i){
        for(int j=1;j<=m;++j){
            for(int k=a[i];k<=b;++k){
                dp[j][k]+=dp[j-1][k-a[i]];
                dp[j][k]%=mod;
            }
        }
    }
    LL res=0;
    for(int i=0;i<=b;++i){
        res+=dp[m][i];
        res%=mod;
    }
    cout<<res<<endl;
    return 0;
}

D. Destroying Roads
一个n个顶点m条边组成的无向图。
求令s1到t1的距离不超过d1,令s2到t2的距离不超过d2. 所能删除的最多的边数

求s1到t1的最短路,s2到t2的最短路
1.s1到t1的路线与s2到t2的路线不相交
2.路线相交,那么枚举相交区间的左右端点 ,类似 H型

#include <bits/stdc++.h>
const int MAXN = 3010;
using namespace std;
vector<int> edge[MAXN];
bool vis[MAXN];
int d[MAXN][MAXN];
int n,m;
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.cpp","r",stdin);
#endif // ONLINE_JUDGE
    int u,v;
    int s1,t1,d1,s2,t2,d2;
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;++i){
        scanf("%d%d",&u,&v);
        edge[u].push_back(v);
        edge[v].push_back(u);
    }
    queue<int> q;
    for(int i=1;i<=n;++i){
        memset(vis,0,sizeof(vis));
        while(!q.empty()) q.pop();
        q.push(i);
        vis[i]=1;
        d[i][i]=0;
        while(!q.empty()){
            u=q.front();q.pop();
            for(int j=0;j<edge[u].size();++j){
                v=edge[u][j];
                if(!vis[v]){
                    vis[v]=1;
                    d[i][v]=d[i][u]+1;
                    q.push(v);
                }
            }
        }
    }
    scanf("%d%d%d %d%d%d",&s1,&t1,&d1,&s2,&t2,&d2);
    if(d[s1][t1]>d1||d[s2][t2]>d2){
        puts("-1");
        return 0;
    }
    int ans=d[s1][t1]+d[s2][t2];
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;++j){
            if(d[s1][i]+d[i][j]+d[j][t1]<=d1&&d[s2][i]+d[i][j]+d[j][t2]<=d2)
                ans=min(ans,d[s1][i]+d[i][j]+d[j][t1]+d[s2][i]+d[j][t2]);
            if(d[s1][i]+d[i][j]+d[j][t1]<=d1&&d[t2][i]+d[i][j]+d[j][s2]<=d2)
                ans=min(ans,d[s1][i]+d[i][j]+d[j][t1]+d[t2][i]+d[j][s2]);
        }
    }
    cout<<m-ans<<endl;
    return 0;
}

E. Remembering Strings
n个长度为m的字符串,替换第i个串第j个字符的花费为aij。一个串为好记的串,当且仅当存在某个位置j字母为c,使得其他串的第j个位置的字母都不为c。求使得n个字符串都为好记的串的最小花费

dp[s]表示使s好记的最小花费
两种决策
1.将第i个串的第j个位置的字母替换掉
2.替换掉这一列与c相同的字母,保留花费最大的那一个

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值