Topcode SRM 556

Topcode SRM 556

没做这次tc,本来计划好要做的,记过被早上七点就起来帮老师排号的事儿忙昏了,把这事儿忘了,上qq的时候才看到群里人谈tc才恍然大悟,立马注册发现已经来不及了……哎,没做就没做,也没有什么遗憾的,至少不会掉ranking

div2 A   水题,顺着题目的思路暴力模拟,然后暴力统计即可

public:
        int find(vector <string> A)
        {
                bool vis[55][55]={0};
                int n=sz(A),m=sz(A[0]);
                for(int i=0;i<n;i++)
                for(int j=0;j<m;j++)
                   if(A[i][j]=='N') vis[i][j+1]=1;
                   else if(A[i][j]=='S') vis[i+2][j+1]=1;
                   else if(A[i][j]=='W') vis[i+1][j]=1;
                   else vis[i+1][j+2]=1;
                int ret=0;
                for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                  if(!vis[i][j]) ret++;
                return ret;
        }

div2 B 开始没有思路,想到到达每个点的XOR有很多,我们不能简单只取改点XOR最大的,这样结果很有可能不是最优的,因为改点XOR小的也可能经过一段路径之后XOR变大了;突破点就在于每个点的val 都在[ 0 ,1023]之间,那么这些数的XOR肯定在[0 ,1023] 范围内,然后每个节点的状态就有[ 0 ,1023]共1024个,然后开个数组记录是否可达就行了,用bfs()实现

typedef long long ll;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<string> VS;
#define PB push_back
#define MP make_pair
#define ff first
#define ss second
#define two(w) (1<<w)
#define sz(v) (int)v.size()
#define all(c) c.begin(),c.end()
#define clr(buf,val) memset(buf,val,sizeof(buf))
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define repv(i,v) for(int i=0;i<(int)v.size();i++)

bool dp[50][1024],vis[50][1024],g[50][50];

class XorTravelingSalesman
{
        public:
        int maxProfit(vector <int> val, vector <string> roads)
        {
            int n=sz(val);
            for(int i=0;i<n;i++)
            for(int j=0;j<n;j++) g[i][j]=(roads[i][j]=='Y');
            memset(vis,0,sizeof(vis));
            clr(dp,0);
            queue<pair<int,int> > q;
            dp[0][val[0]]=1;
            for(q.push(MP(0,val[0]));!q.empty();q.pop())
            {
                int u=q.front().first;
                int v=q.front().second;
                vis[u][v]=0;
                for(int i=0;i<n;i++)
                  if(g[u][i]&&!dp[i][v^val[i]]&&!vis[i][v^val[i]]) dp[i][v^val[i]]=1,vis[i][v^val[i]]=1,q.push(MP(i,v^val[i]));
            }
            int ret=0;
            for(int i=0;i<n;i++)
            for(int j=0;j<1024;j++)
              if(dp[i][j]&&ret<j) ret=j;
            return ret;
        }

div2 C  很容易想到用dp,每个数字明显只有两种选择,一个上放在最后面,一个是放在最前面,而且是限制的,要求最终的数不能包含前导0,比如答案可能是:100000012

0可以放在中间的,所以每个节点要记录该字符之前所有字符(包括该字符)所能组成的合法的数字的最小字符串,和非法的最小字符串,然后状态转移就很简单了

我用的$来标示该状态不存在

typedef long long ll;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<string> VS;
#define PB push_back
#define MP make_pair
#define ff first
#define ss second
#define two(w) (1<<w)
#define sz(v) (int)v.size()
#define all(c) c.begin(),c.end()
#define clr(buf,val) memset(buf,val,sizeof(buf))
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define repv(i,v) for(int i=0;i<(int)v.size();i++)

string dp[50][2];

class LeftRightDigitsGame
{
        public:
        string ins_f(string a,char c)
        {
            if(a=="$") return "$";
            string tmp="";
            tmp+=c;
            for(int i=0;i<a.length();i++) tmp+=a[i];
            return tmp;
        }
        string ins_b(string a,char c)
        {
            if(a=="$") return "$";
            string tmp="";
            for(int i=0;i<a.length();i++) tmp+=a[i];
            tmp+=c;
            return tmp;
        }
        string Max(string a,string b)
        {
            if(a=="$") return b;
            if(b=="$") return a;
            if(a<b) return a;
            return b;
        }
        string minNumber(string dig)
        {
             int n=dig.length();
             if(dig[0]=='0'){
                  dp[0][0]="$";
                  dp[0][1]="0";
             }
             else {
                 dp[0][0]=dig[0];
                 dp[0][1]="$";
             }
            // cout<<dp[0][0]<<" "<<dp[0][1]<<endl;
             for(int i=1;i<n;i++)
             {
                 if(dig[i]!='0'){
                     dp[i][0]=ins_f(dp[i-1][1],dig[i]);
                     dp[i][0]=Max(dp[i][0],ins_f(dp[i-1][0],dig[i]));
                     dp[i][0]=Max(dp[i][0],ins_b(dp[i-1][0],dig[i]));

                     dp[i][1]=ins_b(dp[i-1][1],dig[i]);
                 }else{
                    dp[i][0]=ins_b(dp[i-1][0],dig[i]);

                    dp[i][1]=ins_f(dp[i-1][0],dig[i]);
                    dp[i][1]=Max(dp[i][1],ins_f(dp[i-1][1],dig[i]));
                    dp[i][1]=Max(dp[i][1],ins_b(dp[i-1][1],dig[i]));
                 }
                 //cout<<dp[i][0]<<" "<<dp[i][1]<<endl;
             }
             return dp[n-1][0];
        }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值