A - What a Beautiful Lake

题目链接:https://vjudge.net/contest/331813#problem/A

题意:

给出一串数字,该数字在环上,问你这个环构成的最长的上升或者下降连续子序列的长度

题解:

当时自己代码写错了,wa了几发才知道自己错在了没有考虑如果存在非递增和非递减的情况,其实解法就是将这个数组扩大二倍,从1到2n遍历,找寻最长的上升或者下降子序列的长度

#include <cstdio>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <string>
using namespace std;
#define ll long long
int a[205];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        if(n == 0){
            break;
        }
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
            a[i+n] = a[i];
        }
        int ans = 0,ans1 = 0,ans2 = 0;
        for(int i=1;i<2*n;i++)
        {
            if(a[i] > a[i-1]){
                ans1++;
                ans = max(ans,ans1);
            }else{
                ans1 = 0;
            }

            if(a[i] < a[i-1]){
                ans2++;
                ans = max(ans,ans2);
            }else{
                ans2 = 0;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

B - What a Ridiculous Election

题目链接:https://vjudge.net/contest/331813#problem/B

题意:

给你一个五位数的数字,问你从12345变成这个数字最少需要几步,如果不可能,输出-1。只存在三种操作,第一种是可以将相邻的俩位数字调换,次数不限;第二种是将一个位置上的数字+1然后对10取模,次数仅限3次;第三种操作是将一个位置上的数字*2然后对10取模,次数仅限2次。

题解:

bfs(12345),定义一个三维数组dp[99999][3][2],直接看代码更好懂

#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <string.h>
using namespace std;
#define ll long long
const int maxx = 100005;
int a[maxx][4][3];
int ans[maxx];
struct node{
    int x;
    int k1,k2;
    int cnt;
};
queue<node> q;
int b[6];
int swapp1(int x,int pos)
{
    int sum = 0,k1 = 0,k2 = 1;
    pos = 5-pos+1;
    memset(b,0,sizeof(b));
    while(x){
        b[++sum] = x%10;
        x/=10;
    }
    swap(b[pos],b[pos+1]);
    for(int i=1;i<=5;i++){
        k1 += b[i]*k2;
        k2 *= 10;
    }
    return k1;
}
int swapp2(int x,int pos)
{
    int sum = 0,k1 = 0,k2 = 1;
    pos = 5-pos+1;
    memset(b,0,sizeof(b));
    while(x){
        b[++sum] = x%10;
        x/=10;
    }
    b[pos] = (b[pos]+1)%10;
    for(int i=1;i<=5;i++){
        k1 += b[i]*k2;
        k2 *= 10;
    }
    return k1;
}
int swapp3(int x,int pos)
{
    int sum = 0,k1 = 0,k2 = 1;
    pos = 5-pos+1;
    memset(b,0,sizeof(b));
    while(x){
        b[++sum] = x%10;
        x/=10;
    }
    b[pos] = (b[pos]*2)%10;
    for(int i=1;i<=5;i++){
        k1 += b[i]*k2;
        k2 *= 10;
    }
    return k1;
}
void bfs()
{
    memset(a,0x3f3f3f3f,sizeof(a));
    memset(ans,0x3f3f3f3f,sizeof(ans));
    node now;
    now.x = 12345,now.k1 = 0,now.k2 = 0,now.cnt = 0;
    a[12345][0][0] = 0;
    q.push(now);

    while(!q.empty())
    {
        node pre = q.front();
        q.pop();

        for(int i=2;i<=5;i++)
        {
            node now = pre;
            now.x = swapp1(now.x , i);
            now.cnt += 1;
            if(now.cnt >= a[now.x][now.k1][now.k2])
                continue;
            a[now.x][now.k1][now.k2] = now.cnt;
            q.push(now);
        }
        if(pre.k1 < 3){
            for(int i=1;i<=5;i++)
            {
                node now = pre;
                now.x = swapp2(now.x , i);
                now.cnt += 1;
                now.k1 += 1;
                if(now.cnt >= a[now.x][now.k1][now.k2])
                    continue;
                a[now.x][now.k1][now.k2] = now.cnt;
                q.push(now);
            }
        }
        if(pre.k2 < 2){
            for(int i=1;i<=5;i++)
            {
                node now = pre;
                now.x = swapp3(now.x , i);
                now.cnt += 1;
                now.k2 += 1;
                if(now.cnt >= a[now.x][now.k1][now.k2])
                    continue;
                a[now.x][now.k1][now.k2] = now.cnt;
                q.push(now);

            }

        }
    }
    for(int i=0;i<=99999;i++){
        for(int j=0;j<=3;j++){
            for(int k=0;k<=2;k++){
                ans[i] = min(ans[i] , a[i][j][k]);
            }
        }
    }
    return ;
}
int main()
{
    int n;
    bfs();
    while(~scanf("%d",&n))
    {
        if(ans[n] == 0x3f3f3f3f){
            printf("-1\n");
            continue ;
        }
        printf("%d\n",ans[n]);
    }
    return 0;
}

J - Counting Cliques

题目链接:https://vjudge.net/contest/331813#problem/J

题意:

给出一个无向图的n个点和m条边以及数字k,问你这个图里存在多少个k完全图。k完全图即无向图中有k个点,每俩个点之间都有一条边。

题解:

递归查找答案,从一个点出发,将这个点所有的相连的点都push进一个数组,然后接着重复之间的步骤,直到当数组大小等于k,且第k个点和前k-1个点都有连边,答案加1,第一次用数组当参数传,好像还挺好用的。。。

#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <string.h>

using namespace std;
#define ll long long

int ans = 0, a[105][105];
vector<int> v[105];
int n,m,k;
void solve(int x,int b[],int siz)
{
    for(int i=1;i<siz;i++)
    {
        if(a[b[i]][b[siz]] != 1){
            return ;
        }
    }
    if(siz == k){
        ans++;
        return ;
    }
    for(int i=0;i<v[x].size();i++)
    {
        b[siz+1] = v[x][i];
        solve(v[x][i] ,b , siz+ 1);
    }
}
int main()
{
    int t,x,y;
    scanf("%d",&t);
    while(t--)
    {
        ans = 0;
        memset(a,0,sizeof(a));
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++){
            v[i].clear();
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            v[x].push_back(y);
            a[x][y] = a[y][x] = 1;
        }
        for(int i=1;i<=n;i++)
        {
            int b[12];
            b[1] = i;
            solve(i,b,1);
        }
        cout<<ans<<endl;
    }
    return 0;
}