18hun第二次多校

补中档题(难题不考虑)是不可能补了,前面的还没做完,后面的就来了,还压根不会,只能写写水题,练练英语,压压惊咯。

                                                                                                                                                   -------窃.尼古拉斯致远


A:Sim Card

解题思路:

水题,求最小的花费。

代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>

using namespace std;

int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m) && n && m){
        int ans = 0x3ffffff;
        ans = min(ans,n*30+m*40);
        ans = min(ans,n*35+m*30);
        ans = min(ans,n*40+m*20);
        printf("%d\n",ans);
    }
    return 0;
}

/**********************************************************************
	Problem: 2027
	User: zhiyuanjiang
	Language: C++
	Result: AC
	Time:4 ms
	Memory:2024 kb
**********************************************************************/


B:Bank Card Verifier

解题思路:

水题,根据规则判断一个号码是否有效,题目读了好几遍,果然英语战五渣。

代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>

using namespace std;

typedef long long llt;

int main()
{
    string str,s1,s2,s3,s4;
    while(1){
        cin >> s1 >> s2 >> s3 >> s4;
        if(s1 == "0000" && s2 == "0000" && s3 == "0000" && s4 == "0000") break;
        str = s1+s2+s3+s4;
        llt ans = 0;
        for(int i = 0; i < str.length(); i += 2){
            int t = str[i]-'0';
            t *= 2;
            if(t > 9) t -= 9;
            ans += t;
        }
        for(int i = 1; i < str.length(); i += 2){
            ans += str[i]-'0';
        }
        if(ans%10 == 0) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}


E:Barareh on Fire

解题思路:

广搜,火先蔓延。

代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>

using namespace std;

typedef long long llt;

const int N = 1010;

struct Node{
    int x,y,dis;
    Node(int _x,int _y,int _d){
        x = _x; y = _y; dis = _d;
    }
};
int r,c,t;
int dx[] = {0,0,1,-1,1,-1,1,-1};
int dy[] = {1,-1,0,0,1,-1,-1,1};
char graph[N][N];
vector<Node>p1,p2,f1,f2;

bool inside(int x,int y)
{
    return x >= 0 && x < r && y >= 0 && y < c;
}

int bfs()
{
    p1.clear(); p2.clear();
    f1.clear(); f2.clear();
    int ex,ey,cnt = 0;
    for(int i = 0; i < r; ++i){
        for(int j = 0; j < c; ++j){
            if(graph[i][j] == 'f') f1.push_back(Node(i,j,0));
            if(graph[i][j] == 's') p1.push_back(Node(i,j,0));
            if(graph[i][j] == 't') ex = i,ey = j;
        }
    }

    while(!p1.empty()){

        ++cnt;
        if(cnt == t){
            for(int i = 0; i < f1.size(); ++i){
                Node u = f1[i];
                for(int j = 0; j < 8; ++j){
                    int nx = u.x+dx[j];
                    int ny = u.y+dy[j];
                    if(inside(nx,ny) && graph[nx][ny] != 'f'){
                        graph[nx][ny] = 'f';
                        f2.push_back(Node(nx,ny,0));
                    }
                }
            }

            f1.clear();
            for(int i = 0; i < f2.size(); ++i) f1.push_back(f2[i]);
            f2.clear();
            cnt = 0;
        }

        if(graph[ex][ey] == 'f') return 0;

        for(int i = 0; i < p1.size(); ++i){
            Node u = p1[i];
            for(int j = 0; j < 4; ++j){
                int nx = u.x+dx[j];
                int ny = u.y+dy[j];
                if(inside(nx,ny) && graph[nx][ny] != 'f' && graph[nx][ny] != '#'){
                    graph[nx][ny] = '#';
                    if(nx == ex && ny == ey) return u.dis+1;
                    p2.push_back(Node(nx,ny,u.dis+1));
                }
            }
        }

        p1.clear();
        for(int i = 0; i < p2.size(); ++i) p1.push_back(p2[i]);
        p2.clear();
    }

    return 0;
}

int main()
{
    while(~scanf("%d%d%d",&r,&c,&t) && r && c && t){
        for(int i = 0; i < r; ++i) scanf(" %s",graph[i]);
        int ans = bfs();
        if(ans) printf("%d\n",ans);
        else printf("Impossible\n");
    }
    return 0;
}


H:Column Addition

解题思路:

dp,最长上升子序列。

代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>

using namespace std;

typedef long long llt;

const int N = 1010;

string sa,sb,sc;
int f[N],dp[N],d[N];

int toInt(char ch)
{
    return ch-'0';
}

int main()
{
//    freopen("d:\\h.in","r",stdin);
//    freopen("d:\\out.txt","w",stdout);
    int n;
    while(~scanf("%d",&n) && n){
        cin >> sa >> sb >> sc;
        memset(dp,0,sizeof(dp));
        memset(f,0,sizeof(f));
        memset(d,0,sizeof(d));
        int temp,ans = 0;
        for(int i = n-1; i >= 0; --i){
            for(int j = i+1; j <= n; ++j){
                temp = (toInt(sa[i])+toInt(sb[i])+f[j]);
                if(temp%10 == toInt(sc[i])){
                    if(dp[i] < dp[j]+1) dp[i] = dp[j]+1,f[i] = temp/10;
                }
                if(temp == toInt(sc[i]))
                    ans = max(ans,dp[j]+1);
            }
        }
        printf("%d\n",n-ans);
    }
    return 0;
}


k:Mars

解题思路:

给定一个01串S,然后给你S的子串t,问t修改最少的次数使t不为S的子串。

用后缀自动机可以很快的处理这种有关子串问题。对S串建立后缀自动机,然后让t在自动机上跑,若t的当前字符与自动机的转移字符不一样时,修改串t的代价+1。在自动机上碰到转移字符只有‘1’或‘0’时,若t的当前字符与自动机唯一的转移方向一致,代价+1,否则不变,此时修改结束。然后最小的代价为答案。

在自动机上跑dfs,计算不出它的时间复杂度,没有任何剪枝(不会剪),妥妥的超时。然后抄袭了大佬的剪枝(dfs)终于过了。

代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <map>

using namespace std;

typedef long long llt;

const int INF = 0x3ffffff;
const int N = 10010;

struct state{
    int len,link;
    map<char,int>next;
}st[N*2];

string str;
int sz,last;

void sa_init(int n)
{
    sz = last = 0;
    st[0].len = 0;
    st[0].link = -1;
    ++sz;

    for(int i = 0; i < 2*n; ++i)
        st[i].next.clear();
}

void sa_extend(char c)
{
    int cur = sz++;         //新添加的状态结点
    st[cur].len = st[last].len+1;
    int p;
    for(p = last; p != -1 && !st[p].next.count(c); p = st[p].link)
        st[p].next[c] = cur;
    if(p == -1)
        st[cur].link = 0;
    else{
        int q = st[p].next[c];
        if(st[p].len+1 == st[q].len)
            st[cur].link = q;
        else{
            int clone = sz++;
            st[clone].len = st[p].len+1;
            st[clone].next = st[q].next;
            st[clone].link = st[q].link;
            for(; p != -1 && st[p].next[c] == q; p = st[p].link)
                st[p].next[c] = clone;
            st[q].link = st[cur].link = clone;
        }
    }
    last = cur;
}

int ans;

//u当前自动机上匹配的结点,s子串上匹配的结点
void dfs(int u,int s,int e,int cnt)
{
    if(u == sz-1 && s <= e || s > e || cnt >= ans) return; //剪枝,当前解小于已知最优解直接退出

    char ch = str[s];
    int t = st[u].next.count(ch);
    if(t == 0) ans = min(ans,cnt);
    else dfs(st[u].next[ch],s+1,e,cnt);

    ch = (str[s] == '1' ? '0' : '1');
    t = st[u].next.count(ch);
    if(t == 0) ans = min(ans,cnt+1);
    else dfs(st[u].next[ch],s+1,e,cnt+1);
}

int main()
{
//    freopen("d:\\k.in","r",stdin);
//    freopen("d:\\out.txt","w",stdout);
    int n,k;
    while(~scanf("%d%d",&n,&k) && n && k){
        cin >> str;
        sa_init(str.length());
        for(int i = 0; i < str.length(); ++i)
            sa_extend(str[i]);
        int a,b;
        for(int i = 0; i < k; ++i){
            ans = INF;
            scanf("%d%d",&a,&b);
            if(a == b){
                printf("Impossible\n"); continue;
            }
            dfs(0,a-1,b-1,0);
            if(ans >= INF) printf("Impossible\n");
            else printf("%d\n",ans);
        }
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/jiangzhiyuan123/article/details/79856780
今日推荐