FZU 最小花费(贪心)

现在我还想不明白这道题为什么要这么做,先存着,以后慢慢想,为什么每次做相邻的移动时,要这么

算???据说是每次移动的步数相等的,表达式ans+=min(y,x*len-i);其中len是要交换的1和0之间交换的次数,

而且是从前面遍历,对于每一个0都会找到最后一个1与它交换。然后求最后ans的值就行了

别人的代码:难过以后我会删了写上自己的

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int const MAX = 1e5;
char s[MAX];
int idx[MAX];

int main()
{
	int T;
	scanf("%d", &T);
	while(T--)
	{
		int x, y;
		scanf("%d %d",&x, &y);
		scanf("%s", s);
		int len = strlen(s), cnt = 0;
		for(int i = len - 1; i >= 0; i--)
			if(s[i] == '1')
				idx[cnt ++] = i;
		int ans = 0, now = 0;
		for(int i = 0; i < cnt; i++)
			if(s[i] == '0')
				ans += min(y, x * (idx[now ++] - i));
		printf("%d\n", ans);
	}
}

昨天,跟g讨论了一下,知道了这道题这么做的原因,1和1是不能交换的,比如说01101这串数字,如果想把最后的1和最前面的0交换的话,可以通过直接换和相邻换,相邻换的次数是5-1=4次,过程:第一次:10101;第二次:11001;第三次:11010;第四次:11100;也就说并不是把最后一个1放到最前面,只要最终结果是一样的就好,前面有1就把他们先移过去。总结可得:如果当前1的位置为pos1,0的位置为pos0,那么我们可以通过花费y直接对他们进行交换,或者花费(pos1-pos0)*x对他们进行若干次的相邻交换,这样我们就可以得出公式:min(y,(pos1-pos0)*x);这道题好奇怪,我不明白为什么我从前往后找1的时候会超时,从后往前找就A了,明天就要去参加省赛了,怎么没有一点点激动啊,贴代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
char a[100001];
int b[50001];
int main()
{
	int t,s,i,x,y;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&x,&y);
		scanf("%s",a);
		s=0;
		for(i=strlen(a)-1;i>=0;i--)
		{
			if(a[i]=='1')
				b[s++]=i;;
		}
		int sum=0,cnt=0;
		for(i=0;i<s;i++)
			if(a[i]=='0')
				sum+=min(y,(b[cnt++]-i)*x);	
		printf("%d\n",sum);
	}
} 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值