AtCoder Beginner Contest 082

B - Two Anagrams
题意:给两个字符串a,b,每个字符串中字符的位置可以自由改变,问是否存在一种排列使a的字典序小于b的字典序。
题解:贪心,a从小往大排,b从大往小排,看是否存在a

    #include
    using namespace std;
    typedef long long ll;
    typedef long double db;
    typedef pair<int,int> pii;
    typedef vector<int> vi;
    #define de(x) cout << #x << "=" << x << endl
    #define rep(i,a,b) for(int i=a;i<(b);++i)
    #define all(x) (x).begin(),(x).end()
    #define sz(x) (int)(x).size()
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define lb(x) (x&-(x))
    const int N = 101010;
    char s1[200],s2[200];
    int s1len,s2len;
    int judge()
    {

        int minlen=min(s1len,s2len);
        for(int i=0;iif(s1[i]return 1;
            }
            else if(s1[i]==s2[i])
            continue;
            else return 0;  
        }
        if(s1lenreturn 1;
        else return 0;
    }

    bool cmp1(char a,char b)
    {
        return abool cmp2(char a,char b)
    {
        return a>b;
    }
    int main(){
        scanf("%s",s1);
        scanf("%s",s2); 
        s1len=strlen(s1);
        s2len=strlen(s2);   
        sort(s1,s1+s1len,cmp1);
        sort(s2,s2+s2len,cmp2);
    //  printf("%s\n",s1);
    //  printf("%s\n",s2);
        if(judge()) cout<<"Yes"<else cout<<"No"<return 0;
    }

C

题意:给出一个序列 要使这个序列中所有的数满足ai出现ai次,最少需要删除几个数。
思路:如果ai大于他的出现次数aicnt,就减去aicnt个数;
如果ai小于他的出现次数aicnt,就减去ai个数。
对每种数用map存一下,然后计减去的数的和即可。

    #include
    using namespace std;
    typedef long long ll;
    typedef long double db;
    typedef pair<int,int> pii;
    typedef vector<int> vi;
    #define de(x) cout << #x << "=" << x << endl
    #define rep(i,a,b) for(int i=a;i<(b);++i)
    #define all(x) (x).begin(),(x).end()
    #define sz(x) (int)(x).size()
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define lb(x) (x&-(x))
    const int N = 101010;

    int main(){
        map<int,int> m1;
        int n,tmp,cnt=0;
        cin>>n;
        for(int i=0;iscanf("%d",&tmp);
        m1[tmp]++;
        }
        map<int,int>::iterator it;
        for(it=m1.begin();it!=m1.end();it++)
        {
            if(it->first!=it->second)
            {
                if(it->first < it->second)
                cnt+=it->second-it->first;
                else
                cnt+=it->second;
            }
        }
        cout<return 0;
    }

D
题意:一个机器人站在0,0点,方向朝向X轴正方向。给出一个操作序列 由F和T组成。如果是T 机器人可以转90度(方向随意),如果是F,就向对应方向前进一格。给出一个长度<=8000的操作序列和一个最终位置(x,y),询问这个位置是否能到达。
思路:把序列拆成x轴和Y轴上的两个数组,对XY轴的移动分别考虑。对于每个轴上的序列,即考虑:一个序列a1,a2,a3,…,an 通过加减运算得到目标值x。
对于这个子问题,我用dfs,最后果然TLE,水不过去了= =
正解用了类似的DP【i】表示i点可不可以到达。因为和的范围为【-8000,8000】,所以DP开16000+就够了。每次加入一个ai,考虑最多16000个dp[i]是否可以转移到。这样就从O(2^m)降低到了O(n*m).16000*8000还够。
以后状态空间有限的时候可以标记每个空间的状态解决问题。

    #include
    using namespace std;
    typedef long long ll;
    typedef long double db;
    typedef pair<int,int> pii;
    typedef vector<int> vi;
    #define de(x) cout << #x << "=" << x << endl
    #define rep(i,a,b) for(int i=a;i<(b);++i)
    #define all(x) (x).begin(),(x).end()
    #define sz(x) (int)(x).size()
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define lb(x) (x&-(x))
    const int N = 101010;
    int dp[2][17000]; 
    int main(){

        string s;
        cin>>s;
        int x,y;
        cin>>x>>y;

        vector<int> list[2];
        int isrow=1,sum=0;
        for(int i=0;ichar c=s[i];
            if(c=='F')
            sum++;
            else if(c=='T')
            {
                list[isrow].pb(sum);
                sum=0;
                isrow=(isrow+1)%2;
            }
        }
        list[isrow].pb(sum);
    //  for(int i=0;i
    //  for(int i=0;i
        dp[0][8500]=1;//0点 
        dp[1][8500]=1;//0点 
        for(int ff=0;ff<2;ff++)
        {
            for(int i=0;i<list[ff].size();i++)
            {
                int x=list[ff][i];
                int temp[17000];
                memset(temp,0,sizeof(temp));
                for(int j=0;j<17000;j++)//+-8000
                {
                    if(dp[ff][j]==1)
                    {
                        if(i==0&&ff==1)
                        temp[j+x]=1;
                        else
                        {
                            temp[j+x]=1;
                            temp[j-x]=1;
                        }
                    } 
                }
                memcpy(dp[ff],temp,sizeof(temp)); 
            }
        }
        if(dp[0][y+8500]&&dp[1][x+8500])
        cout<<"Yes"<else 
        cout<<"No"<return 0;
    }

你可能感兴趣的:(dp,搜索,贪心)