HDU5375 Gray code

应该算是水题,然而比赛的时候就是敲不出来,以为某段?之间的最小值只能在两端取到,结果一直wa。其实,一段内都有可能是最小值,所以去掉这个最小值去掉就可以了。代码写的有点冗长。

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <sstream>
using namespace std;

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

typedef long long LL;
const double pi=4.0*atan(1.0);
const int MAXN=200005;
const int INF=20000;
char s[MAXN];
int a[MAXN];
int qianzui[MAXN];//前缀和
//奇偶指?个数
/* 0偶数1  */
/* 1偶数0  */
/* 0奇数0  */
/* 1奇数1  */
//以上四种一定能使所对应的值全部取到
//其余情况必须舍去一个最小值
int main()
{

	int i,j,k;    
	int cas=1;
	int temp,sum,ans,sign;
	int slen,len;
	int T;
	//freopen("1007.in","r",stdin);
	//freopen("out.txt","w",stdout);
	while(scanf("%d",&T)!=EOF)
	{
		for(cas=1;cas<=T;cas++)
		{
			//最前面加个'0',去掉了 ???数字 的情况
			s[0]='0';
			scanf("%s",s+1);
			slen=strlen(s);
			a[0]=0;
			qianzui[0]=0;
			sum=0;
			for(i=1;i<slen;i++)
			{
				scanf("%d",a+i);
				qianzui[i]=qianzui[i-1]+a[i];
			}
			i=0;
			int left,right;
			ans=0;
			int mm;
			while(i<slen)
			{
				sign=0;
				mm=INF;
				//找第一个? 并记录下标
				for(;i<slen;i++)
				{
					if(s[i]=='?')
					{
						left=i;
						sign=1;
						break;

					}
				}
				if(sign==0)//如果sign==0,那么意味着剩下的全是数字
					break;
				for(;i<slen;i++)
				{

					if(s[i]!='?')
					{
						mm=min(a[i],mm);
						right=i;
						break;
					}
					else
					{
						mm=min(a[i],mm);
					}
				}

				if(i==slen)//此时代表 数字???...?
				{
					//一定都能取到
					ans+=qianzui[slen-1]-qianzui[left-1];
				}
				else
				{
					//left,right一定在
					right--;
					len=right-left+1;

					if(s[left-1]=='0'&&s[right+1]=='0'||(s[left-1]=='1'&&s[right+1]=='1'))
					{
						if(len%2==1)
						{
							ans+=qianzui[right+1]-qianzui[left-1];
						}
						else
						{
							ans+=qianzui[right+1]-qianzui[left-1];
							ans-=mm;
						}
					}
					else 
					{
						if(len%2==0)
						{
							ans+=qianzui[right+1]-qianzui[left-1];
						}
						else
						{
							ans+=qianzui[right+1]-qianzui[left-1];
							ans-=mm;
						}

					} 
				}
			}
			//算上确定的值
			for(i=1;i<slen;i++)
			{
				if(s[i-1]!='?'&&s[i]!='?')
				{
					int t1=s[i-1]-'0';
					int t2=s[i]-'0';
					ans+=(t1^t2)*a[i];
				}
			}
			printf("Case #%d: %d\n",cas,ans);

		}
	}
	return 0;
}

早上起来写dp,确实dp更简单,但是自己写得和别人的怎么差距那么大。还有好长一条路要走!

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <sstream>
using namespace std;

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

typedef long long LL;
const double pi=4.0*atan(1.0);
const int MAXN=200005;
char s[MAXN];
int a[MAXN];
int dp[MAXN][3];
int main()
{

	int i,j,k;    
	int cas=1;
	int n,t;
	//freopen("1007.in","r",stdin);
	//freopen("out.txt","w",stdout);
	int ans,sum;
	int T;
	while(scanf("%d",&T)!=EOF)
	{
		int cas=1;
		
		while(T--)
		{
			s[0]='0';
			scanf("%s",s+1);
			
			int len=strlen(s);
			for(i=1;i<len;i++)
				scanf("%d",a+i);
			memset(dp,0,sizeof(dp));
			if(s[1]=='0')
				dp[1][1]=dp[1][0]=0;
			else if(s[1]=='1')
			{
				dp[1][1]=a[1];
				dp[1][0]=0;
			}
			else
			{
				dp[1][1]=a[1];
				dp[1][0]=0;
			}
			for(i=2;i<len;i++)
			{
				if(s[i]=='0')
				{
					if(s[i-1]=='0') 
						dp[i][0]=dp[i-1][0];
					else if(s[i-1]=='1')
						dp[i][0]=dp[i-1][1]+a[i];
					else 
						dp[i][0]=max(dp[i-1][0],dp[i-1][1]+a[i]);
					
				}
				else if(s[i]=='1')
				{
					if(s[i-1]=='0')
						dp[i][1]=dp[i-1][0]+a[i];
					else if(s[i-1]=='1') 
						dp[i][1]=dp[i-1][1];
					else 
						dp[i][1]=max(dp[i-1][1],dp[i-1][0]+a[i]);
				}
				else
				{
					if(s[i-1]=='0')
					{
						dp[i][0]=dp[i-1][0];
						dp[i][1]=dp[i-1][0]+a[i];
					}
					else if(s[i-1]=='1')
					{
						dp[i][0]=dp[i-1][1]+a[i];
						dp[i][1]=dp[i-1][1];
					}
					else
					{
						dp[i][0]=max(dp[i-1][1]+a[i],dp[i-1][0]);
						dp[i][1]=max(dp[i-1][0]+a[i],dp[i-1][1]);;
					}
					
				}
			}
			if(s[len-1]=='0')
				printf("Case #%d: %d\n",cas++,dp[len-1][0]);
			else if(s[len-1]=='1')
				printf("Case #%d: %d\n",cas++,dp[len-1][1]);
			else
				printf("Case #%d: %d\n",cas++,max(dp[len-1][1],dp[len-1][0]));
		}
			
	}
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值