zoukankan      html  css  js  c++  java
  • UESTC 2014 Summer Training #20

      卡了好几天,总算把DAY 20的基础题写了...(对我来说还是很卡手的

    (8.13 22:49正准备完结这一天的时候,突然发现挂掉的A题还没写...先去补上再来总结)

    A.Gift from the Goddess of Programming Aizu 1315

      一个人一天可以进去多次,模拟没啥好说的,只有我这种傻逼才会写挂

    B.The Sorcerer's Donut Aizu 1316

      题意:给你一个大写字母的矩阵,可以从任一点任一方向拓展(八个方向,无边界),最多拓展到起点,问重复出现过的字符串最长的是哪一个,多解输出字典序最小的,

    解的长度必须大于等于2

      就是一个暴力枚举+map判重

      可以记录一个当前最优解的长度maxlen(重复出现过的字符串最长长度, 初始为2), 只有当枚举的字符串长度大于等于这个值, 才进行操作

      如果串没出现过,map标记下,出现过的话,长度是否等于maxlen?添加当前串到解集:更新长度,解集清空,加入当前解

      解集就是一个string数组,最后sort下输出ans[0]

      整体看下来,代码量还是很小的,就是自己第一次写map~

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <string>
    #include <map>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 40;
    const int dx[] = {1, -1, 0, 0 , 1, 1, -1, -1},
               dy[] = {0, 0, 1, -1, 1, -1, 1, -1};
    
    int n, m, ml, cnt;
    char donut[maxn][maxn];
    string ans[2000];
    map<string, int> mp;
    
    int main()
    {
    #ifdef LOCAL
        freopen("B.in", "r", stdin);
    #endif
        while(scanf("%d%d", &n, &m) != EOF) {
            if(n == 0 && m == 0)    break;
            ml = cnt = 0;
            mp.clear();
            for(int i = 0; i < n; i++)
                scanf("%s", donut[i]);
            for(int i = 0; i < n; i++)
                for(int j = 0; j < m; j++) 
                    for(int k = 0; k < 8; k++) {
                        string tmp = "";
                        int nx = i, ny = j;
                        do{
                            tmp += donut[nx][ny];
                            if(tmp.size() >= 2 && tmp.size() >= ml) {
                                if(!mp[tmp])    mp.insert(pair <string, int> (tmp, 1));    
                                else if(tmp.size() == ml && mp[tmp] == 1) 
                                    ans[cnt++] = tmp;
                                else if(tmp.size() > ml) {
                                    ml = tmp.size();
                                    cnt = 0;
                                    ans[cnt++] = tmp;
                                }
                            }
                            mp[tmp]++;                        
                            nx = (nx+dx[k]+n)%n;
                            ny = (ny+dy[k]+m)%m;
                        }while(nx != i || ny != j);    
    //                    cout << tmp << endl;    
                        /*
                        if(!mp[tmp])    mp.insert(pair <string, int> (tmp, 1));    
                        else {
                            if(tmp.size() == ml && mp[tmp] == 1) {
                                ans[cnt++] = tmp;
                            }
                            else if(tmp.size() > ml) {
                                ml = tmp.size();
                                cnt = 0;
                                ans[cnt++] = tmp;
                            }
                            mp[tmp]++;
                        }
                        */
                    }
            sort(ans, ans+cnt);
            if(cnt)    printf("%s
    ", ans[0].c_str());
            else    printf("0
    ");
        }
        return 0;
    }

    D.Long Distance Taxi Aizu 1318

      训练的时候是想出了正确解法,只是自己不敢去写,也确实写不出来....
      容易想到,要么不经过加油站,要么经过,经过加油站的话,最后一定从某个加油站出发到达终点,可以重新建一个图,只包含加油站和终点起点

      先对这些点都跑一遍最短路,在gas*10的距离内能达到的点,就连一条边,表示以满油状态这两个点可以互达(这里就把限制条件解决了)

      再对新建的图跑一遍最短路就解决问题了...

      通过传递参数,只需要写一个spfa(也是回味了下怎么写spfa....)

      细节比较麻烦的是一开始的建图,可以用map来标记已经读入过的点(已经分配了序号)

      我的代码:一开始建图是1~n(所有点),后面重新建图是按照加入到vector gast里面的顺序0~n

      调试了挺久。。。各种错误T T  好弱好弱啊

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <vector>
    #include <queue>
    #include <map>
    #include <string>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 6000;
    const int maxm = 6090;
    const int inf = ~0u >> 2;
    
    struct Edge{
        int v, w;
        Edge() {}
        Edge(int v, int w) {
            this->v = v;    this->w = w;
        }
    };
    
    int n, m, gas, ncnt;
    vector<int> gast;
    vector<Edge> g1[maxn], g2[maxm];
    map<string, int> mp;
    
    void addNode(string s)
    {
        if(!mp[s])    mp[s] = ++ncnt;
    }
    
    void addEdge(int u, int v, int w)
    {
        g1[u].push_back(Edge(v, w));
        g1[v].push_back(Edge(u, w));
    }
    
    void spfa(int x, int dis[], vector<Edge> g[])
    {
        queue<int> q;
        bool inqueue[maxn];
        memset(inqueue, 0, sizeof(inqueue));
        inqueue[x] = 1;    q.push(x); dis[x] = 0;
        while(!q.empty()) {
            int tmp = q.front();    q.pop();    inqueue[tmp] = false;
            for(int i = 0; i < g[tmp].size(); i++) {
                int v = g[tmp][i].v, w = g[tmp][i].w;
                if(dis[tmp]+w < dis[v]) {
                    dis[v] = dis[tmp]+w;
                    if(!inqueue[v]) {
                        q.push(v);
                        inqueue[v] = true;;
                    }
                }    
            }
        }    
    }
    
    int main()
    {
    #ifdef LOCAL
        freopen("D.in", "r", stdin);
    #endif
        while(scanf("%d%d%d", &m, &n, &gas) != EOF) {
            if(m == 0 && n == 0)    break;
            ncnt = 0;
            char stmp[maxm], estmp[maxm]; 
            gast.clear();
            mp.clear();
            for(int i = 0; i < maxn; i++)    g1[i].clear();
            for(int i = 0; i < maxm; i++)    g2[i].clear();
            scanf("%s%s", stmp, estmp);
            addNode(stmp);    addNode(estmp);
            for(int i = 0; i < m; i++) {
                int w;
                scanf("%s%s%d", stmp, estmp, &w);
                addNode(stmp);    addNode(estmp);
                addEdge(mp[stmp], mp[estmp], w);
            }
            gast.push_back(1);    gast.push_back(2);
            for(int i = 1; i <= n; i++) {
            //if one vertex is unique, ignore it
                scanf("%s", stmp);
                if(mp[stmp])    gast.push_back(mp[stmp]);
            }
            //calc single-point shortest path for every gas station and set-up point
            //rebuild a graph with vertices including stations and beginning and end point
            for(int i = 0; i < gast.size(); i++) {
                int x = gast[i];
                int dis[maxn];
                fill(dis, dis+ncnt+1, inf);
                spfa(x, dis, g1);
                for(int j = 0; j < gast.size(); j++)
                    if(dis[gast[j]] <= gas*10)     g2[i].push_back(Edge(j, dis[gast[j]]));
            }
            int dis[maxm];
            fill(dis, dis+gast.size()+1, inf);
            spfa(0, dis, g2);    
            printf("%d
    ", dis[1] != inf ? dis[1] : -1);
        }
        return 0;
    }

    F.City Merger Aizu 1320

      N = 14 真该往状压dp去想= =

      先预处理出每个串放其他串后面会增加的长度(奥 先剔除子串 可以保证一个串不会覆盖到第三个串去)

      然后我们可以想到f[i]表示已经选了state=i这些串的最短长度,然后再放一个串到后面去

      只需要再添加一维f[i][j]表示以j串结尾,就能update (以上只是模拟可能想到此题思路的一种思维过程。。。)

      奥 需要注意的是更新的时候 如果f[i][j]没有计算 就直接赋值 如果已经算出来了就 取最小值(因为可以由多种状态去update这个状态)

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <vector>
    
    using namespace std;
    
    const int maxn = 30;
    
    int n;
    int extra[maxn][maxn], f[1<<15][maxn];
    char word[maxn][maxn];
    bool substr[maxn];
    vector<char*> wd;
    
    int main()
    {
    #ifdef LOCAL
        freopen("F.in", "r", stdin);
    #endif
        while(scanf("%d", &n) != EOF) {
            if(n == 0)    break;
            memset(substr, 0, n*sizeof(char));
            wd.clear();
            for(int i = 0; i < n; i++) {
                scanf("%s", word+i);
                for(int j = 0; j < i; j++) {
                    if(strstr(word[i], word[j]) != NULL)    substr[j] = true;
                    else if(strstr(word[j], word[i]) != NULL)    substr[i] = true;
                }
            }
            for(int i = 0; i < n; i++)
                if(!substr[i])    wd.push_back(word[i]);
            for(int i = 0; i < wd.size(); i++)
                for(int j = 0; j < wd.size(); j++) {
                    int plen = strlen(wd[i]), nlen = strlen(wd[j]), match = 0;
                    for(int k = min(nlen, plen); k > 0; k--)
                        if(strncmp(wd[j], wd[i]+plen-k, k) == 0)    {
                            match = k;
                            break;
                        }
                    extra[i][j] = nlen-match;
                }
            int cnt = wd.size();
            memset(f, 0, sizeof(f));
            for(int i = 0; i < cnt; i++)
                f[1<<i][i] = strlen(wd[i]);
            for(int i = 1; i < (1 << cnt); i++) 
                for(int j = 0; j < cnt; j++) {
                    if(((1<<j)&i) == 0)    continue; 
                    for(int k = 0; k < cnt; k++) {
                        if((1<<k)&i)    continue; 
                        int now = i|(1<<k); 
                        f[now][k] = f[now][k]? min(f[now][k], f[i][j]+extra[j][k]):f[i][j]+extra[j][k]; 
    //                    if(i == 13)
    //                    cout << "Insert " <<  k << " after " << j << ' ' << f[now][k] << endl; 
                    } 
                } 
            int ans = cnt*maxn; 
            for(int i = 0; i < cnt; i++) 
                ans = min(ans, f[(1<<cnt)-1][i]); 
            printf("%d
    ", ans); 
        }
        return 0; 
    }

      卡了4天终于把坑补上了。。还不算J题压根没看

      训练时A题写了一遍WA就没心情写了,其实呢...B题还是可以尝试一发的

      就越来越弱哎~

      

  • 相关阅读:
    fstest
    iozone
    fio
    vdbench
    饼状图点击凸出,适合颜色选择
    个人常用的win7快捷键
    form表单提交数据
    jquery允许跨越获取cookie
    设置滚动条样式与监听滚动到底部
    设置滚动条样式与监听滚动到底部
  • 原文地址:https://www.cnblogs.com/gemmeg/p/3911361.html
Copyright © 2011-2022 走看看