Codeforces Round 930 (Div. 2)

substr时间复杂度O(N),不能一遍遍找,会超时  

#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
const int N=5e5+10;
map<string,int>mp;
vector<string>v[N];
int main()
{
	int t;cin>>t;
	while(t--)
	{
		int n;cin>>n;
		string s1,s2;cin>>s1>>s2;
		mp.clear();
		string ss;
		for(int i=0;i<=n;i++)
		{
			ss+="1";
		}
		for(int i=0;i<n;i++)
		{
		    string x=s1[0]+s1.substr(1,i)+s2.substr(i);
			mp[x]++;
	        //out<<s1.substr(0,i)<<" "<<s2.substr(i)<<endl;
			if(x<ss) ss=x;
		}
		cout<<ss<<endl<<mp[ss]<<endl;
	}
	return 0;
}

 

#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
const int N=5e5+10;
map<string,int>mp;
vector<string>v[N];
int main()
{
	int t;cin>>t;
	while(t--)
	{
		int n;cin>>n;
		string s1,s2;cin>>s1>>s2;
	    string x=s1+s2[n-1];
	    int num=n-1;
	    int flag=0;
	    //substr时间复杂度O(n) 不可一一查询会超时 
	    for(int i=0;i<n;i++)
	    {
	    	//找到这个点时就是最佳的拐点 
	    	if(s1[i]=='1'&&s2[i-1]=='0')
	    	{
	    		x=s1.substr(0,i)+s2.substr(i-1);
	    		num=i-1;
	    		break;
			}
		}
		int cnt=1;
		for(int j=num;;j--)
		{
			//倒着走不相等 就不可以了 如果相等说明向下向右都可以即++ 一定是连续的交叉相等
			//一旦出现不相等 就结束 即方案数 
			if(s1[j]!=s2[j-1]) break;
			cnt++;
		}
		cout<<x<<endl<<cnt<<endl;
	}
	return 0;
}

 DP

#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
const int N=5e5+10;
map<string,int>mp;
vector<string>v[N];
int main()
{
	int t;cin>>t;
	while(t--)
	{
		int n;cin>>n;
		int arr[2][n];
		int dp[2][n];
		for(int i=0;i<=1;i++)
	    {
	    	string s;cin>>s;
	    	for(int j=0;j<n;j++)
	    	{
	    		arr[i][j]=s[j]-'0';//首先预处理 
	    		dp[i][j]=0;//dp值预处理 
			}
		}
		dp[0][0]=1;//初始点唯一,一个方案 
		string ans;
		ans+=(char)(arr[0][0]+'0');//然后初始点也要在路径字符串上算上 
		for(int i=0;i<=n-1;i++)//总共移动步数 
		{
			int tmp=1;
			//第一部分 看后面能不能转移到0 
			for(int j=0;j<=1;j++)//向下几次 
			{
				//枚举当前可能的点 走不了 不可能转移次数大于移动次数
				if(j>i) continue; 
				int x=j,y=i-j;//找出枚举的点 
				if(dp[x][y]==0) continue;//如果这个点不能被走到 就continue 
				if(x==0)//否则能向下 
				{
					if(arr[x+1][y]==0)//看向下能不能走到0 
					{
						tmp=0;
					}
				}
				if(y<=n-2)//能向右 
				{
					if(arr[x][y+1]==0)
					{
						tmp=0;//看向右能不能走到0
					}
				}
			}
			//把目前添加的字符添加进去 
			if(tmp==0) ans+='0';
			else ans+='1';
			//第二部分,我们再把应该转移的去转移一下 
			for(int j=0;j<=1;j++)
			{
				if(j>i) continue;
				int x=j ,y=i-j;
				if(dp[x][y]==0)continue;
				if(x==0)
				{
					if(arr[x+1][y]==tmp)
					{
						dp[x+1][y]+=dp[x][y];
					}
				}
				if(y<=n-2)
				{
					if(arr[x][y+1]==tmp)
					{
						dp[x][y+1]+=dp[x][y];
					}
				}
			}
		 } 
		cout<<ans<<endl;
		cout<<dp[1][n-1]<<endl;
	}
	return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值