srm 556 div1 500 LeftRightDigitsGame2(DP)

Problem Statement

 You are playing a solitaire game called Left-Right Digits Game. This game uses a deck of N cards. Each card has a single digit written on it. These digits are given as characters in the string digits. More precisely, the i-th character of digits is the digit written on the i-th card from the top of the deck (both indices are 0-based). 



The game is played as follows. First, you place the topmost card (whose digit is the 0-th character of digits) on the table. Then, you pick the cards one-by-one from the top of the deck. For each card, you have to place it either to the left or to the right of all cards that are already on the table. 



After all of the cards have been placed on the table, they now form an N-digit number. You are given a string lowerBound that represents an N-digit number. The primary goal of the game is to arrange the cards in such a way that the number X shown on the cards will be greater than or equal to lowerBound. If there are multiple ways to satisfy the primary goal, you want to make the number X as small as possible. 



Return the smallest possible value of X you can achieve, as a string containing N digits. If it is impossible to achieve a number which is greater than or equal to lowerBound, return an empty string instead.

Definition

 
Class:LeftRightDigitsGame2
Method:minNumber
Parameters:string, string
Returns:string
Method signature:string minNumber(string digits, string lowerBound)
(be sure your method is public)
 
 

Notes

-lowerBound has no leading zeros. This means that any valid number X should also have no leading zeros (since otherwise it will be smaller than lowerBound).

Constraints

-digits will contain between 1 and 50 characters, inclusive.
-Each character of digits will be between '0' and '9', inclusive.
-lowerBound will contain the same number of characters as digits.
-Each character of lowerBound will be between '0' and '9', inclusive.
-The first character of lowerBound will not be '0'.

Examples

0) 
 
"565"
"556"
Returns: "556"
You can achieve exactly 556. The solution is as follows:
  • Place the first card on the table.
  • Place the second card to the right of all cards on the table.
  • Place the last card to the left of all cards on the table.
1) 
 
"565"
"566"
Returns: "655"
2) 
 
"565"
"656"
Returns: ""
The largest number you can achieve is 655, but it is still less than 656.
3) 
 
"9876543210"
"5565565565"
Returns: "5678943210"
4) 
 
"8016352"
"1000000"
Returns: "1086352"

题意:给你一个两个字符串,要你用第一个字符串按左到右取,每次可以放在新串的左边或右边,使得新的串大于等于第二个串,并且使这个串最小

分析:一开始没啥思路,不过将过程反过来,就大概有点思路了,从右往左选若干个字符,倒过来放在开头,剩下的字符顺序接在后面,也就是使得这样的串满足条件,我第一反应就是dfs。。。然后就无尽的wa。。。最后搞得剩下一组数据tle。。。TLE

大概猜到正解是DP了,所以看了下题解,具体挺有意思的一个状态表示,就不细讲了,可以去做一下,呵呵

代码:


// BEGIN CUT HERE

// END CUT HERE
#line 5 "LeftRightDigitsGame2.cpp"
#include<cstdlib>
#include<cctype>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<sstream>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<fstream>
#include<numeric>
#include<iomanip>
#include<bitset>
#include<list>
#include<stdexcept>
#include<functional>
#include<utility>
#include<ctime>
using namespace std;
#define PB push_back
#define MP make_pair
#define REP(i,n) for(i=0;i<(n);++i)
#define FOR(i,l,h) for(i=(l);i<=(h);++i)
#define FORD(i,h,l) for(i=(h);i>=(l);--i)
typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<double> VD;
typedef long long LL;
typedef pair<int,int> PII;
class LeftRightDigitsGame2
{
public:
    bool vis[55][55][3][3];
    string f[55][55][3][3],ds,lb,ans;
    int n;
    string solve(int l,int r,int sl,int sr)
    {
        if(l+r>=n)
        {
            if(sl==0||(sl==1&&sr==0))return "*";
            return "";
        }
        string &ret=f[l][r][sl][sr],tmp;
        if(vis[l][r][sl][sr])return ret;
        vis[l][r][sl][sr]=1;
        ret="*";
        int slt=sl,srt=sr;
        if(sl==1)
        {
            if(ds[n-l-r-1]<lb[l])slt=0;
            if(ds[n-l-r-1]>lb[l])slt=2;
        }
        tmp=solve(l+1,r,slt,sr);
        if(tmp!="*")ret=ds[n-l-r-1]+tmp;
        if(ds[n-l-r-1]>lb[n-r-1])srt=2;
        if(ds[n-l-r-1]<lb[n-r-1])srt=0;
        tmp=solve(l,r+1,sl,srt);
        if(tmp!="*")
        {
            tmp=tmp+ds[n-l-r-1];
            if(ret=="*")ret=tmp;
            else ret=min(ret,tmp);
        }
        return ret;
    }
    string minNumber(string _ds, string _lb)
    {
        ds=_ds,lb=_lb;
        memset(vis,0,sizeof(vis));
        n=ds.size();
        ans=solve(0,0,1,1);
        if(ans=="*")ans="";
        return ans;
    }

// BEGIN CUT HERE
	public:
	void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); if ((Case == -1) || (Case == 4)) test_case_4(); }
	private:
	template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
	void verify_case(int Case, const string &Expected, const string &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
	void test_case_0() { string Arg0 = "068"; string Arg1 = "356"; string Arg2 = "608"; verify_case(0, Arg2, minNumber(Arg0, Arg1)); }
	void test_case_1() { string Arg0 = "310938"; string Arg1 = "847579"; string Arg2 = "890133"; verify_case(1, Arg2, minNumber(Arg0, Arg1)); }
	void test_case_2() { string Arg0 = "565"; string Arg1 = "656"; string Arg2 = ""; verify_case(2, Arg2, minNumber(Arg0, Arg1)); }
	void test_case_3() { string Arg0 = "9876543210"; string Arg1 = "5565565565"; string Arg2 = "5678943210"; verify_case(3, Arg2, minNumber(Arg0, Arg1)); }
	void test_case_4() { string Arg0 = "8016352"; string Arg1 = "1000000"; string Arg2 = "1086352"; verify_case(4, Arg2, minNumber(Arg0, Arg1)); }

// END CUT HERE

};
// BEGIN CUT HERE
int main()
{
    LeftRightDigitsGame2 ___test;
    ___test.run_test(-1);
    return 0;
}
// END CUT HERE


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值