机试-搜索专题

机试-搜索专题

深搜

堆和栈的区别:
https://www.cnblogs.com/myblesh/archive/2012/03/14/2396409.html
定义全局变量或者自己malloc,栈的空间是有限的。

背包问题
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
// 输出背包问题的最佳方案
const int maxn = 20000;
int n,v;
int w[maxn];
int c[maxn];
vector<int> tmp,ans;
int maxc;
void dfs(int i,int sumw,int sumc)
{
    if (i == n)
    {
        if (sumc > maxc)
        {
            maxc = sumc;
            ans = tmp; // the way of vector assign
        }
        return ;
    }
    if (sumw+w[i] <= v)
    {
       tmp.push_back(i);
       dfs(i+1,sumw+w[i],sumc+c[i]);
       tmp.pop_back();
    }
    dfs(i+1,sumw,sumc);
}
int main()
{
    while (cin>>n>>v)
    {
        for (int i=0;i<n;i++)
            cin >> w[i];
        for (int i=0;i<n;i++)
            cin >> c[i];
        dfs(0,0,0);
        for (int i=0;i<ans.size();i++)
            cout << ans[i] << ' ';
        cout << endl;
        cout << maxc << endl;

    }


    return 0 ;
}

N个数选K个使平方和最大且和为X

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
// 从N个数中选择K个数,使和为x的基础上平方和最大
const int maxn = 2000;
int n,k,x;
int maxsum;
vector<int> tmp,ans;
int a[maxn];
void dfs(int i,int num,int sum,int psum)
{
    // i 代表第i个被选择的数,num代表一共挑选的数的个数,sum为其和,psum为平方和
    if (i==n)
    {
        if (psum > maxsum && num == k && sum == x)
        {
            maxsum = psum;
            ans = tmp;
        }
        return ;
    }
    dfs(i+1,num,sum,psum);
    if (sum+a[i]<=x)
    {
        tmp.push_back(a[i]);
        dfs(i+1,num+1,sum+a[i],psum+a[i]*a[i]);
        tmp.pop_back();
    }
}
int main()
{
    while (cin>>n>>k>>x)
    {
        maxsum = 0;
        for (int i=0;i<n;i++)
            cin >> a[i];
        dfs(0,0,0,0);
        for (int i=0;i<ans.size();i++)
            cout << ans[i] << ' ';
        cout << endl;
        cout << maxsum << endl;
    }


    return 0 ;
}
// 1.127s
void dfs(int i,int num,int sum,int psum)
{
    // K个并且和为X时才判断
    if (num == k && sum == x)
    {
        if (sum > maxsum)
        {
            maxsum = sum;
            ans = tmp;
        }
        return ;
    }
    // 其他情况直接return 
    if (i>n-1 || num > k || sum>x)
        return ;
    if (a[i]+sum <= x)
    {
        tmp.push_back(i);
        dfs(i+1,num+1,sum+a[i],psum+a[i]*a[i]);
        tmp.pop_back();
    }
    dfs(i+1,num,sum,psum);
}

codeforces round 479 D divide by three, multiple by two

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;


int n;
long long a[101];
bool visited[101];
long long f[101];

bool dfs(int &k)
{
    if (k==n)
        return true;
    long long x = f[k-1];
    for (int i=0;i<n;i++)
    {
        if (visited[i])
            continue;
        if ((a[i] == x/3 && (x%3==0)) || a[i] == x*2)
        {
            f[k++] = a[i];
            visited[i] = true;
            if (dfs(k)) return true;
            visited[i] = false;
            k--;
        }
    }
    return false;
}
int main()
{

    int k;
    while (cin>>n)
    {
        for (int i=0;i<n;i++)
        {
           cin >> a[i];visited[i] = false;
        }
        k = 0;
        for(int i=0;i<n;i++)
        {
            visited[i] = true;
            f[k++] =  a[i];
            if (dfs(k)) break; // 只要找到一组就直接break,不用继续循环了
            visited[i] = false;
            k--;
        }
        for (int i=0;i<n;i++)
            cout << f[i] <<' ';
        cout << endl;



    }

    return 0 ;
}

return true / false / break 是为了在找到正确答案后立即输出而不是继续循环到末尾

解法2

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;

// divide by three, multiple by two
int n;
long long a[101];// 8B 2^64 = 1024^6 = e^18
vector<long long >ans;
bool flag,visited[101] ;
void dfs(int i,int sum) // i: the i th number ; sum:selected number
{
    if (sum==n)
    { 
        for (int i=0;i<n-1;i++)
            cout << ans[i] << ' ';
        cout << ans[n-1]<<endl;
        flag = true;
        return ;
    }

    //4 8 6 3 12 9
    for (int j=0;j<n;j++)
    {
        if (i!=j && !visited[j])
        {
            if ((a[j]==a[i]/3 && a[i]%3==0) || a[j] == a[i]*2 )
            {
                ans.push_back(a[j]);visited[j]=true;
                dfs(j,sum+1);
                if (!flag)
                {
                  ans.pop_back();visited[j] = false;
                }
            }
        }
    }
}
int main()
{
   while (cin>>n)
   {
       for (int i=0;i<n;i++)
       {
         cin >> a[i];visited[i]=false;
       }

        ans.clear();
        flag = false;
       for (int i=0;i<n;i++)
       {
           ans.push_back(a[i]);visited[i]=true;
           dfs(i,1);
           ans.pop_back();visited[i] = false;
       }

   }



    return 0 ;
}

全排列

  • 10 min
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
// 全排列
int n,sum;
bool visited[101];
vector<int> ans;
void dfs(int sum)
{
    if (sum == n)
    {
        for (int i=0;i<n-1;i++)
            cout << ans[i] <<" ";
        cout << ans[n-1] << endl;
        return;
    }
    for (int i=1;i<=n;i++)
    {
        if (!visited[i])
        {
           visited[i]= true;
           ans.push_back(i);
           dfs(sum+1);
           visited[i]= false;
           ans.pop_back();
        }
    }
}
int main()
{
   while  (cin>>n)
   {
       for (int i=1;i<=n;i++)
       {
           visited[i] = false;
       }
       ans.clear();
       dfs(0); // 选择0个元素
   }


    return 0 ;
}

组合 递归

  • 15min
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
// 递归 求组合
int n,r,num; // num:selected numbers
vector<int > ans;
void dfs(int i,int num)
{
    // 判断第I个数是否要被选择
    if (i == n)
    {
        if (num == r)
        {
            for (int i=0;i<r-1;i++)
            cout << ans[i] <<" ";
            cout << ans[r-1] << endl;
        }
        return;
    }
    ans.push_back(i+1);
    dfs(i+1,num+1);
    ans.pop_back();

    dfs(i+1,num);
}
int main()
{
   while  (cin>>n>>r)
   {
       ans.clear();
       dfs(0,0);//
   }


    return 0 ;
}

组合 非递归

?????????????????????????????

#define _CRT_SECURE_NO_WARNINGS
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <set>

using namespace std;

void permutation(int n, int m)
{
    vector<int> combine;
    stack<int> buf;
    bool pop = false;
    int top;

    buf.push(1);
    combine.push_back(1);

    while (buf.size())
    {
        if (combine.size() == m)
        {
            for (int i = 0; i < m; ++i)
            {
                printf("%d", combine[i]);
                if (i != m - 1)
                    printf(" ");
            }
            printf("\n");
            pop = true;
        }

        top = buf.top() + 1;
        if (top == n + 1)
        {
            pop = true;
            buf.pop();
            combine.pop_back();
            continue;
        }

        if (pop)
        {
            buf.pop();
            combine.pop_back();
            pop = false;
        }

        if (top <= n)
        {
            buf.push(top);
            combine.push_back(top);
        }
    }

}

int main()
{
#ifdef _DEBUG
    freopen("data.txt", "r+", stdin);
#endif // _DEBUG

    int n, m, PS = 0;

    while (cin >> n >> m)
    {
        permutation(n, m);
    }



    return 0;
}

组合数+判断素数

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
// 递归 求组合
int n,k,num,ans,ans_num; // num:selected numbers
int a[21];
bool visited[21];

bool isSu(int x)
{
    for (int i=2;i<sqrt(x)+1;i++)
    {
        if (x%i == 0)
        {
           return false;
        }
    }
    return true;

}
void dfs(int i,int num)
{
    // 判断第I个数是否要被选择
    if (i == n)
    {
        if (num == k && isSu(ans))
        {
         ans_num++;
        }
        return;
    }
    if (num+1 <= k )
    {
        ans += a[i+1];
        dfs(i+1,num+1);
        ans -= a[i+1];
    }
    dfs(i+1,num);
}
int main()
{
   while  (cin>>n>>k)
   {
       for (int i=1;i<=n;i++)
       {
          cin >> a[i]; visited[i]=  false;
       }
       ans = 0;ans_num = 0;
       dfs(0,0);
       cout << ans_num << endl;
   }


    return 0 ;
}

N皇后

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
// N皇后问题
int n,num;
bool visited[11];
vector<int> ans;
bool flag = false;
bool isok(int i,int j)
{
    // 判断第I行皇后能否放在J个列
    // 1. 不可能同一行,因为I从1-n
    // 2. 同一列
    if (visited[j])
        return false;
    // 3. 对角线
    // i,j / k, l |i-k| = |k-l| 时两个点在对角线上
    for (int k = 1;k<i;k++)
    {
        if (abs(k-i) == abs(ans[k-1]-j))
            return false;
    }
    return true;
}
void dfs(int i)
{
    if (i==n)
    {
        flag = true;
        for (int j=0;j<n-1;j++)
            cout << ans[j] << " ";
        cout << ans[n-1] << endl;
        return ;
    }
    for (int j=1;j<=n;j++)
    { // j : column
        if (isok(i+1,j))
        {
            visited[j] = true;
            ans.push_back(j);
            dfs(i+1);
            visited[j] = false;
            ans.pop_back();
        }

    }
}
int main()
{
   while  (cin>>n)
   {
       ans.clear();
       for (int i=0;i<=n;i++)
        visited[i] = false;
       dfs(0);
       if (!flag)
        cout<<"no solute!" <<endl;
   }


    return 0 ;
}

迷宫

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
// 走迷宫
int n,m;
int a[101][16];
struct point
{
    int x,y;
};
point s,e,t;

vector<point> ans;
void print()
{
    for (int i=0;i<ans.size()-1;i++)
    {
        cout << "("<<ans[i].x<<","<<ans[i].y<<")->";
    }
    cout << "("<<ans[ans.size()-1].x<<","<<ans[ans.size()-1].y<<")"<<endl;
}
int dir[4][2] = {
0,-1,
-1,0,
0,1,
1,0
};
void dfs(point p)
{ // p:当前位置
    if (p.x == e.x && p.y == e.y)
    {
        print();
        return;
    }
    if (p.x<1 || p.x > n || p.y < 1 || p.y > m)
        return ; // meet border return
    if (a[p.x][p.y] == 0)
        return ; // meet wall return
    for (int i=0;i<4;i++)
    {
        t = p;
        // 四个方向即四个分支可以深搜
        t.x = p.x+dir[i][0];
        t.y = p.y+dir[i][1];
        // 已经访问过的点再往下深搜的过程中不会再次访问,可以设为wall
        a[p.x][p.y] = 0;
        ans.push_back(t);
        dfs(t);
        a[p.x][p.y] = 1;
        ans.pop_back();

    }

}
int main()
{

    while (cin>>n>>m)
    {
        for (int i=1;i<=n;i++)
        {
            for (int j=1;j<=m;j++)
            {
                cin >> a[i][j];
            }
        }
        ans.clear();
        cin >> s.x >> s.y;
        cin >> e.x >> e.y;
        ans.push_back(s);
        dfs(s);


    }


    return 0 ;
}
  • 本地运行正确但提交不正确

jugs

?????????????????????????????????????????????????????????????????????

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
using namespace std;
int ca,cb,n;
struct node
{
    int x,y;
    struct node *parent;
    string word;
}s,e,tmp,cur;
queue<node> q;
vector<string> w;
int main()
{
    while (cin>>ca>>cb>>n)
    {
        while (!q.empty())
            q.pop();
        w.clear();
        s.x = 0;s.y = 0;s.parent = NULL;
        e.y = n;
        q.push(s);
        while (!q.empty())
        {
            cur = q.front();
            q.pop();
            // ÅжÏÊÇ·ñΪ×îÖÕ̬
            if (cur.y == e.y)
            {
                string t = "success";
                w.push_back(t);
                struct node *p;p=&cur;
              while (p->parent!=NULL)
              {
                 w.push_back(p->word);
                 p = p->parent;
              }
              for (int i = w.size()-1;i>=0;i--)
              {
                  cout << w[i] << endl;
              }
            }


            if (cur.x < ca)
            {
                tmp = cur;
                // A is not full
                tmp.x = ca;
                tmp.word = "fill A";
                tmp.parent = &cur;
                q.push(tmp);
            }

            if (cur.y < cb)
            {
                tmp = cur;
                // B is not full
                tmp.y = cb;
                tmp.word = "fill B";
                tmp.parent = &cur;
                q.push(tmp);
            }

            if (cur.x > 0)
            {
                tmp = cur;
                // A is not empty
                tmp.x = 0;
                tmp.word = "empty A";
                tmp.parent = &cur;
                q.push(tmp);
            }

            if (cur.y > 0)
            {
                tmp = cur;
                // B is not empty
                tmp.y = 0;
                tmp.word = "empty B";
                tmp.parent = &cur;
                q.push(tmp);
            }

            if (cur.x > 0 && cur.y < ca)
            {
                tmp = cur;
                if (cur.x >= cb-cur.y) // x more than capacity of B
                {
                    tmp.y = cb;
                    tmp.x = cur.x - cb + cur.y;
                }
                else
                {
                    tmp.y = cur.x+cur.y;
                    tmp.x = 0;
                }
                tmp.word = "pour A B";
                tmp.parent = &cur;
                q.push(tmp);
            }

            if (cur.y > 0 && cur.x < ca)
            {
                tmp = cur;
                // B have water and A has place to hold
                if (cur.y >= ca-cur.x) // y more than capacity of A
                {
                    tmp.x = ca;
                    tmp.y = cur.y - ca + cur.x;
                }
                else
                {
                    tmp.x = cur.x+cur.y;
                    tmp.y = 0;
                }
                tmp.parent = &cur;
                tmp.word = "pour B A";
                q.push(tmp);
            }
        }
    }
    return 0 ;
}
  • char 型迷宫定义成int型导致爆莫名奇妙的错误。

掉石头迷宫

???????????????
应该是迷宫状态更新的问题。 1.5小时

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
using namespace std;
// 掉石头迷宫问题
int t1;
char a[9][9],t[9][9];
struct point
{
    int x,y,t;
}s,e,tmp,cur;
vector<point> stone;
queue<point> q;
void printa(char a[9][9])
{
   for (int i=1;i<=8;i++)
        {
            for (int j=1;j<=8;j++)
                cout << a[i][j] << " ";
            cout << endl;
        }
}
void flush(char a[9][9]) // 石头状态刷新一次
{
  /*  int x1,y1;
    for (int i=0;i<stone.size();i++)
    {
        x1 = stone[i].x;
        y1 = stone[i].y;
        a[x1][y1] = '.';
        if (x1+1 <=8) // 超出边界的石头则删除了
            a[x1+1][y1] = 'S';
    }

    */
    for (int i=1;i<9;i++)
    {
        for (int j=1;j<9;j++)
        {
            if (a[i][j] == 'S')
            {
               a[i+1][j] = 'S';
               a[i][j] = '.';
            }
        }
    }

}
int dir[9][2] =
{
-1,0,
-1,1,
0,1,
1,1,
1,0,
1,-1,
0,-1,
-1,-1,
0,0
};
bool judge(point tmp)
{
    if (tmp.x < 1 || tmp.y >8 || tmp.y < 1 || tmp.y > 8)
        return false;
    if (a[tmp.x][tmp.y] == 'S' || t[tmp.x][tmp.y] == 'S') // 移动后所在位置有石头或移动后石头下落砸到自己
        return false;
    return true;
}
int main()
{
    cin >> t1;
    bool flag;
    while (t1--)
    {
        flag = false;
        // 输入迷宫
        for (int i=1;i<=8;i++)
        {
            for (int j=1;j<=8;j++)
            {
               cin >> a[i][j]; t[i][j] = a[i][j];
            }
        }

        /* 存石头位置
        stone.clear();
        for (int i=1;i<9;i++)
        {
            for (int j=1;j<9;j++)
            {
                if (a[i][j] == 'S')
                {
                   tmp.x = i;tmp.y = j;
                   stone.push_back(tmp);
                }
            }
        }
        */
        // 清空队列
        while (!q.empty())
            q.pop();
        // 初始化队列
        s.x = 8;s.y = 1;e.x = 1;e.y = 8;s.t = 0;
        q.push(s);
        while (!q.empty())
        {
            cur = q.front();q.pop();
            if (cur.x == e.x && cur.y == e.y)
            {
                flag = true;
                break;
            }
            flush(t);  // t是移动后的a
            printa(t);
            for (int i=0;i<9;i++)
            {
                tmp = cur;
                tmp.x += dir[i][0];
                tmp.y += dir[i][1];
                tmp.t ++;
                if (judge(tmp))
                {
                    q.push(tmp);
                }
            }
            flush(a);//a t 同步了
            printa(a);

        }
        if (flag)
            cout << "Yes" << endl;
        else
            cout << "No" << endl;
        getchar();
    }
    return 0 ;
}

DP

斐波那契

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
using namespace std;

int fib(int n)
{
    if (n==1 || n==2)
        return 1;
    else
        return fib(n-1)+fib(n-2);
}
int main()
{
    int n;
    while (cin >> n)
    {
        cout << fib(n) << endl;
    }
    return 0 ;
}
  • n <= 30 最简单的递归,内存超限: 大量的重复的计算
  • 方法:通过空间的损耗来提高计算的速度,一维数组DP记录每个数的数值,未计算过则设置为-1。
  • 记忆化搜索 每个数仅算一遍
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
using namespace std;

int dp[32];
int fib(int n)
{
    if (n==1 || n==2) // 递归边界
    {
       return 1;
    }
    if (dp[n]!=-1)
        return dp[n]; // 先判断我们的缓存里面有没有,有的话直接取出否则递归计算
    else
    {
        dp[n] = fib(n-1)+fib(n-2);
        return dp[n];
    }

}
int main()
{
    int n;
    while (cin >> n)
    {
        for (int i=0;i<32;i++) dp[i] = -1;
        cout << fib(n) << endl;
    }
    return 0 ;
}

最大连续子序列和

????????????????? 如何输出最大连续的子序列呢?

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
using namespace std;

int dp[32];
bool flag[32];
int a[10001];
int main()
{
    int n;
    while (cin >> n)
    {
        for (int i=0;i<n;i++) 
        {cin >> a[i];flag[i] = false;}
        dp[0] = a[0];

        for (int i=1;i<n;i++)
        {
            dp[i] = max(a[i],dp[i-1]+a[i]);
        }




    }
    return 0 ;
}
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
using namespace std;

int dp[32];
bool flag[32][32];
int a[10001];
int main()
{
    int n;
    while (cin >> n)
    {
        for (int i=0;i<n;i++)
        {cin >> a[i];}
        for (int i=0;i<32;i++)
        {
            for (int j=0;j<32;j++)
                flag[i][j] = false;
        }
        dp[0] = a[0]; flag[0][0] = true;

        for (int i=1;i<n;i++)
        {
            dp[i] = max(a[i],dp[i-1]+a[i]);
            if (dp[i] == a[i])
            {
                flag[i][i] = true;
            }
            else
            {
                for (int x=0;x<i;x++)
                    flag[i][x] = flag[i-1][x];
                flag[i][i] = true;
            }
        }
        int k = 0;
        int max = dp[0];
        for (int i=1;i<n;i++)
        {
            if (dp[i] > max)
            {
                max = dp[i]; k = i;
            }
        }
        for (int i=0;i<n;i++)
        {
            if (flag[k][i])
                cout << a[i] <<" ";
        }





    }
    return 0 ;
}
  • 运行错误? 还是格式错误?

最长上升子序列

http://codeup.cn/problem.php?cid=100000627&pid=0

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
using namespace std;


int main()
{
    int n;
    int dp[32];
    int a[10001];
    while (cin >> n)
    {
        for (int i=0;i<n;i++)
        {cin >> a[i];dp[i] = 1;}


        for (int i=1;i<n;i++)
        {
            for (int j=0;j<i;j++)
            {
                if (a[j] < a[i])
                {
                    dp[i] = max(dp[i],dp[j]+1);
                }
            }
        }
        sort(dp,dp+n);
        cout << dp[n-1] << endl;


    }
    return 0 ;
}

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
using namespace std;

const int maxn = 200001;
int a[maxn];
int n;
int dp[maxn];
int main()
{
    while (cin>>n)
    {
        for (int i=0;i<n;i++)
             cin >> a[i];
        dp[0] = 1;
        int ans = 0; // 最大dp值的下标
        for (int i=1;i<n;i++)
        {
            for (int j=0;j<i;j++)
            {
                if (a[j] == a[i]-1)
                {
                    dp[i] = max(dp[i],dp[j]+1); // 找到最大的
                }
            }
            if (dp[i] > dp[ans])
            {
                ans = i;
            }
        }
        cout << dp[ans] << endl;
        vector<int> p;p.clear();
        for (int i = ans,j=0;i>=0;i--)
        {
            if (a[i] == a[ans]-j)
            {
               p.push_back(i);j++;
            }

        }
        for (int i=p.size()-1;i>0;i--)
            cout << p[i]+1 <<" ";
        cout << p[0]+1 << endl;

    }

    return 0 ;
}

time limited 超时了!

用map存储:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
using namespace std;

const int maxn = 200001;
int a[maxn];
int n;
int dp[maxn];
map<int,int> m;
int main()
{
    while (cin>>n)
    {
        m.clear();
        for (int i=0;i<=n;i++)
            m[i] = 0;
        for (int i=1;i<=n;i++)
        {
            cin >> a[i];
            m[a[i]] = m[a[i]-1]+1;
        }
        int ans = 0,k=0;
        map<int,int>::iterator it;
        for (it = m.begin();it !=m.end();it++)
        {
            if (it->second > ans)
            {
                ans = it->second;
                k = it->first;
            }
        }
        int pos = k - ans + 1;
        cout << ans << endl;
        for (int i=1;i<=n&&pos <= k;i++ )
        {
            if (a[i] == pos)
            {
                cout << i <<" ";
                pos++;
            }
        }



    }

    return 0 ;
}

非常可乐

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
using namespace std;

int coco,n,m;
struct status
{
    int a,b,c,d;
}s,cur,tmp;
queue<status> q;
const int maxn = 101;
int v[maxn][maxn][maxn];
void pour(int a,int b,int c,int d)
{
    if (!v[a][b][c])
    {
        v[a][b][c] = 1;
        tmp.a = a;
        tmp.b = b;
        tmp.c = c;
        tmp.d = d+1; // 未出现的状态才倒水,并加入队列
        q.push(tmp);
    }
}
int bfs(int a,int b,int c,int d) // d为倒水次数,a,b,c为杯中可乐量
{
    while (!q.empty()) q.pop();
    s.a = coco;s.b = s.c = s.d = 0; // 初始状态
    q.push(s);
    v[coco][0][0] = 1; // 该状态已入队过,为防止重复入队
    while (!q.empty())
    {
        cur = q.front();q.pop();
        if ((cur.a == coco/2 && cur.b == coco/2 )||(cur.a == coco/2 && cur.c == coco/2 ) || (cur.b == coco/2 && cur.c == coco/2 ) )
            return cur.d;
        //s->n:
        if (cur.a > 0 && cur.b < n) // a has coco and b is not full
            pour(cur.a - n + cur.b, n, cur.c, cur.d);
        //s->m;
        if ( cur.a > 0 && cur.c < m)
            pour(cur.a - m + cur.c, cur.b, m, cur.d);
        //n->s;
        if (cur.b > 0 && cur.a < coco)
            pour(cur.a + cur.b, 0, cur.c, cur.d);
        //m->s;
        if (cur.c > 0 && cur.a < coco )
            pour(cur.a + cur.c, cur.b, 0, cur.d);
        //n->m
        if (cur.b > 0 && cur.c < m)
        {
          if(cur.b > m - cur.c)
            pour(cur.a, cur.b - m + cur.c, m, cur.d);
          else
            pour(cur.a, 0, cur.b + cur.c, cur.d);
        }

        //m->n
        if (cur.c > 0 && cur.b < n)
        {
            if(cur.c > n - cur.b)
                pour(cur.a, n, cur.c - n + cur.b, cur.d);
            else
                pour(cur.a, cur.b + cur.c, 0, cur.d);
        }

    }
    return 0;
}
int main()
{
    int ans;
    while (cin>>coco>>n>>m)
    {
        memset(v,0,sizeof(int)*maxn*maxn*maxn);
        if (coco==0)
            break;
        if (coco%2 == 1)
        {
            cout<< "NO" << endl;continue;
        }
        ans = bfs(coco,0,0,0);
        if ( ans > 0)
        {
            cout << ans << endl;
        }
        else
            cout<< "NO" << endl;
    }


    return 0 ;
}

导弹拦截系统:最长不降子序列

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
using namespace std;

const int maxn = 1001;
int main()
{
    int n;
    int a[maxn];
    int dp[maxn]; // 以I为结尾的不降子序列的长度
    while (cin>>n)
    {
        for (int i=0;i<n;i++)
        {
           cin >> a[i]; dp[i] = 1;
        }
        int ans = 1;
        for (int i=1;i<n;i++)
        {
            for (int j=0;j<i;j++)
            {
                if (a[j] < a[i])
                {
                    dp[i] = max(dp[j]+1,dp[i]);
                }
            }
            if (dp[i] > ans)
                ans = dp[i];
        }
        cout <<ans<< endl;



    }
    return 0 ;
}

猜你喜欢

转载自blog.csdn.net/qq_33846054/article/details/80736860