CodeForces#286 div.2 题解

来源:互联网 发布:ajax json遍历 编辑:程序博客网 时间:2024/06/07 07:00

题目链接:http://codeforces.com/contest/505/problems

分类:A、枚举 ;B、BFS;C、DP;D、强联通;E、不明


A题:

题意:在字符串的任意任意位置插入一个字符,使得得到的字符串回文

思路:数据范围很小,字符串长度才10,一共276种情况,枚举就行了。

下面是A题代码:

#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <vector>#include <deque>#include <list>#include <cctype>#include <algorithm>#include <climits>#include <queue>#include <stack>#include <cmath>#include <map>#include <set>#include <iomanip>#include <cstdlib>#include <ctime>#define ll long long#define ull unsigned long long#define all(x) (x).begin(), (x).end()#define clr(a, v) memset( a , v , sizeof(a) )#define pb push_back#define mp make_pair#define read(f) freopen(f, "r", stdin)#define write(f) freopen(f, "w", stdout)using namespace std;const double pi = acos(-1);inline bool judge ( const string str ){    int a = 0;    int b = str.size() - 1;    for ( ; a <= b ; ){        if ( str[a] != str[b] ){            return 0;        }        a ++;        b --;    }    return 1;}int main(){    ios::sync_with_stdio( false );    string a;    string b;    cin >> a;    int cnt = 0;    for ( int i = 0; i <= a.size(); i ++ ){        for ( int j = 0; j < 26; j ++ ){            b = a;            string k = "a";            k[0] = k[0] + j;            b.insert ( i, k );            if ( judge ( b ) ){                cout << b << endl;                return 0;            }        }    }    cout << "NA" << endl;    return 0;} 

B题:

题意:给出一张无向图,每条边都有对应的颜色,并且每次只能利用同一种颜色的边。求从a点移动到b点有多少种方案。

思路:同上题,数据范围相当小,只有100个节点,颜色也不超过100种,直接对a点的进行搜索,枚举有多少种颜色的通路能到b点

下面是B题代码:

#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <vector>#include <deque>#include <list>#include <cctype>#include <algorithm>#include <climits>#include <queue>#include <stack>#include <cmath>#include <map>#include <set>#include <iomanip>#include <cstdlib>#include <ctime>#define ll long long#define ull unsigned long long#define all(x) (x).begin(), (x).end()#define clr(a, v) memset( a , v , sizeof(a) )#define pb push_back#define mp make_pair#define read(f) freopen(f, "r", stdin)#define write(f) freopen(f, "w", stdout)using namespace std;const double pi = acos(-1);const int maxn = 1005;vector<int> g[maxn][maxn];bool SPFA ( int be, int en, int k ){    queue<int> que;    que.push ( be );    int vis[1000] = { 0 };    while ( ! que.empty() ){        int tmp = que.front();        que.pop();        for ( int i = 0; i < g[k][tmp].size() && vis[tmp] == 0; i ++ ){            que.push( g[k][tmp][i] );            if ( g[k][tmp][i] == en )                return 1;        }        vis[tmp] = 1;    }    return 0;}int main(){    ios::sync_with_stdio( false );    int m, n;    while ( cin >> m >> n ){        int a, b, c;        for ( int i = 0; i < n; i ++ ){            cin >> a >> b >> c;            g[c][a].push_back ( b );            g[c][b].push_back ( a );        }        int k;        cin >> k;        int be, en;        for ( int i = 0; i < k; i ++ ){            cin >> be >> en;            int cnt = 0;            for ( int j = 1; j <= n; j ++ ){                if ( SPFA ( be, en, j ) ) {                    cnt ++;                }            }            cout << cnt << endl;        }    }    return 0;}


C题:

题意:从起点移动到终点,每次只能比前一次移动距离+1,-1,或者不变。每移动到一个点就将该点的值累加,求最大的情况。

思路:动态规划,有第一维表示位置,第二维表示步长,并且最长步长不能超过250,(1+2+3+.....+250) > 30000 , 所以第二维第长度为500,状态转移方程为 dp[i][j] = dp[i][j] + max ( dp[i-(j-301+n)][j-1], dp[i-(j-301+n)][j], dp[i-(j-301+n)][j+1]  ); ans = max ( ans, f[i][j] );

下面是C题代码:

#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <vector>#include <deque>#include <list>#include <cctype>#include <algorithm>#include <climits>#include <queue>#include <stack>#include <cmath>#include <map>#include <set>#include <iomanip>#include <cstdlib>#include <ctime>#define ll long long#define ull unsigned long long#define all(x) (x).begin(), (x).end()#define clr(a, v) memset( a , v , sizeof(a) )#define pb push_back#define mp make_pair#define read(f) freopen(f, "r", stdin)#define write(f) freopen(f, "w", stdout)using namespace std;const double pi = acos(-1);int num[30005];int dp[30005][605];int main(){    memset ( dp, -1, sizeof ( dp ) );    memset ( num, 0, sizeof ( num ) );    int m, n;    int k;    cin >> m >> n;    for ( int i = 0; i < m; i ++ ){        cin >> k;        num[k] ++;    }    int ans = num[n];    for ( int i = 0; i <= 30000; i ++ ){        for ( int j = 0; j <= 601; j ++ ){            dp[i][j] = -9999999;        }    }    dp[n][301] = num[n];    for ( int i = n + 1; i <= 30000; i ++ ){        for ( int j = 1; j <= 600; j ++ ){            if ( i - ( j - 301 + n ) < 0 || i - ( j - 301 + n ) >= i )continue;            dp[i][j] = max ( dp[i][j], dp[i-(j-301+n)][j-1] );            dp[i][j] = max ( dp[i][j], dp[i-(j-301+n)][j]   );            dp[i][j] = max ( dp[i][j], dp[i-(j-301+n)][j+1] );            dp[i][j] += num[i];            ans = max ( ans, dp[i][j] );        }    }    cout << ans << endl;}

D题:

题意:给出n个节点与m条有向边,判断最少需要边保证连通性不变

思路:最先想到的判断强联通,一个连通块中有若存在强联通分量,则需要的边数=节点数,若不存在强联通,则需要的边数=节点数-1;然后分别对每个连通块进行查询

PS:本来判强联通想通过tarjan染色,搞了好久搞不出来,看别人代码的时候看到了一种很神奇的代码,就拿来学习了下,果然大有收获。

下面是D题代码:

#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <vector>#include <deque>#include <list>#include <cctype>#include <algorithm>#include <climits>#include <queue>#include <stack>#include <cmath>#include <map>#include <set>#include <iomanip>#include <cstdlib>#include <ctime>#define ll long long#define ull unsigned long long#define all(x) (x).begin(), (x).end()#define clr(a, v) memset( a , v , sizeof(a) )#define pb push_back#define mp make_pair#define read(f) freopen(f, "r", stdin)#define write(f) freopen(f, "w", stdout)using namespace std;const double pi = acos(-1);#define MAX_V 100005int V, E;int dfn[MAX_V], low[MAX_V];bool instack[MAX_V];int un[MAX_V];int din;int cnt;int colorCnt = 0;stack<int>s;vector<int>Edge[MAX_V];vector<int>g[MAX_V];vector<int>ans;int vis[MAX_V];void init( int m ){    for ( int i = 0; i < MAX_V; i ++ ){            Edge[i].clear();    }    for ( int i = 0; i <= MAX_V; i ++ ){        un[i] = i;    }    ans.clear();    while ( ! s.empty() )s.pop();    clr ( dfn, 0 );    clr ( low, 0 );    clr ( vis, 0 );    clr ( instack, 0 );}int find ( int x ){    if ( x == un[x] ){        return x;    }    else{        return un[x] = find( un[x] );    }}void merge ( int x, int y ){    x = find( x );    y = find( y );    if ( x == y )return;    un[x] = y;    return;}int bfs ( int i ){    if ( Edge[i].size() >= 2 ){        int cnt = 0;        queue<int> q;        for ( int j = 0; j < Edge[i].size(); j ++ ){            if ( vis[Edge[i][j]] == 0 ) q.push( Edge[i][j] );        }        while ( ! q.empty() ){            int x = q.front();            q.pop();            cnt ++;            for ( int j = 0; j < g[x].size(); j ++ ){                vis[g[x][j]] --;                if ( vis[g[x][j]] == 0 ) q.push( g[x][j] );            }        }        if ( cnt == Edge[i].size() ){            return Edge[i].size() - 1;        }        else{            return Edge[i].size();        }    }    return 0;}int main(){    ios::sync_with_stdio( false );    int m, n;    while ( cin >> m >> n ){        init ( m );        int a, b;        for ( int i = 0; i < n; i ++ ){            cin >> a >> b;            a --;            b --;            merge ( a, b );            g[a].push_back( b );            vis[b] ++;        }        for ( int i = 0; i < m; i ++ ){            Edge[find(i)].push_back( i );        }        int ans = 0;        for ( int i = 0; i < m; i ++ ){            ans += bfs ( i );        }        cout << ans << endl;    }}


E题没做。


(未完待续)

0 0