这题的思维难度不是很大,属于编程实现细节处理较多的题。

暂且把每个字符串的“beauty”称为魅力值,用一个优先队列数组将同一个字符串的所有魅力值保存,通过map将不同字符串编号,就可以十分方便的查询到每个字符按串对应的魅力值队列了。之所以使用优先队列,是因为先处理魅力值更大的才能使得最后的回文串魅力值的和最大。

每个字符串氛围回文串和非回文串,应该分开考虑。

1.先处理非回文字符串,非回文字符串必须把它本身和它的对称串同时处理,因为两个才能对称嘛。

首先取两个字符串队首的魅力值:

int m=q[h].top(); q[h].pop();
int n=q[f].top(); q[f].pop();

对于m和n,当m<0,直接退出;

如果m+n<=0 直接退出;

如果m+n>0   加入最后的答案即可.

2.然后处理较为复杂的回文串。特别注意,回文串可以单独放置一个,因为它自身就是对称的。

1.如果回文串队列中只剩余1个字符串,即q[h].size()==1

如果小于等于0,直接退出;

如果大于零,不能直接退出,因为它可能最后被选中作为单独放置。当然,最后可能会出现多个可能单独放置的回文串,显而易见应该选择魅力值最大的回文串。因此直接用一个变量把最大值保存即可。

2.如果回文串队列中,剩余多个字符串时,取队首前两个元素:

int m=q[h].top(); q[h].pop();
int n=q[h].top(); q[h].pop();

如果m<=0,直接退出;

如果m>0&&n>=0,则将m+n加入最后答案;

如果m>0&&n<0,若m+n>0,此时m、n面临两种选择,要么直接选择m和n直接加入最后答案,或择将m作为单独放置。当然此时无法做出最佳选择,应该加入另外一个结构体数组中,结构体中存储两个元素m和n;若m+n<=0直接将m与此时最大单独放置的值进行比较,取较大值,之所以能直接作为单独放置的选择,是因为m+n<0对最后的答案没有帮助,如果只选择m可能会有帮助。

3.最后一步就是处理单独的放置最大值,以及结构体数组:

因为一定要选择一个单独放置的回文串,那么就枚举结构体数组,如果结构体数组中某个元素的m作为单独放置之后,其他元素一定会全部取m+n,因为要使得最后的魅力值之和最大,也可能是去原先单独放置的最大值,同时把结构体中所有元素都取m+n。

我想可能很多地方都没有讲清楚,大家对这题有什么问题欢迎提出。

AC代码:

#include<cstdio>
#include<map>
#include<queue>
#include<vector>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5+5;
struct node{
	int a,b;
	node(){}
	node(int a,int b):a(a),b(b){
	}
}w[maxn];
string str[maxn];
string rever(string p){
	string s="";
	for(int i=p.size()-1;i>=0;--i){
		s+=p[i];
	}
	return s;
}
bool is_pal(string p){
	int x=0,y=p.size()-1;
	while(x<y){
		if(p[x]!=p[y]) return false;
		x++;
		y--;
	}
	return true;
}
map<string,int>ha1,ha2;
priority_queue<int>q[maxn];
vector<node>pal;
int main(){
	int k,n;
	while(scanf("%d%d",&k,&n)!=EOF){

		int big=0; //最大选择
		string a;
		int b;
		int x=-1;
		for(int i=0;i<k;++i){
			cin>>a>>b;
			str[i]=a;
			int ind;
			if(!ha2.count(a)) {
				++x;
				ind=x;
				ha2[a]=x;
			}
			else ind=ha2[a];
			q[ind].push(b);
		}
		int ans=0;
		for(int i=0;i<k;++i){
			if(ha1[str[i]]==1) continue;
			ha1[str[i]]=ha1[rever(str[i])]=1;
			int h=ha2[str[i]];
			if(is_pal(str[i])){
				if(q[h].empty()||q[h].top()<=0) continue;
				while(!q[h].empty()&&q[h].top()>0){
					if(q[h].size()==1){
						if(q[h].top()>0) big=max(big,q[h].top());
						q[h].pop();
					}
					else {
						int m=q[h].top(); q[h].pop();
						int n=q[h].top(); q[h].pop();
						if(m>0){
							if(n<0) {
								if(m+n>0) pal.push_back(node(m,n));
								else big=max(big,m);
							}
							else if(n>=0) ans+=m+n;
						}
					}
				}
			}
			else{
				if(q[h].empty()) continue;
				string s=rever(str[i]);
				if(!ha2.count(s)) continue; //找不到对称串
				int f=ha2[s];
				while(!q[h].empty()&&!q[f].empty()){
					int m=q[h].top(); q[h].pop();
					int n=q[f].top(); q[f].pop();
					if(m+n<=0) break;
					else if(m+n>0) ans+=m+n;
				}
			}
		}
		int sum=0;
		for(int i=0;i<pal.size();++i){
			sum+=pal[i].a+pal[i].b;
		}
		int u=sum+big;
		for(int i=0;i<pal.size();++i){
			if(pal[i].a>big) u=max(u,sum-pal[i].b);
		}
		ans+=u;
		printf("%d\n",ans);
	}
	return 0;
} 

如有不当之处欢迎指出!

CodeForces-748D 贪心的更多相关文章

  1. CodeForces - 748D Santa Claus and a Palindrome (贪心+构造)

    题意:给定k个长度为n的字符串,每个字符串有一个魅力值ai,在k个字符串中选取字符串组成回文串,使得组成的回文串魅力值最大. 分析: 1.若某字符串不是回文串a,但有与之对称的串b,将串a和串b所有的 ...

  2. CodeForces - 893D 贪心

    http://codeforces.com/problemset/problem/893/D 题意 Recenlty Luba有一张信用卡可用,一开始金额为0,每天早上可以去充任意数量的钱.到了晚上, ...

  3. Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem D (Codeforces 831D) - 贪心 - 二分答案 - 动态规划

    There are n people and k keys on a straight line. Every person wants to get to the office which is l ...

  4. Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) Problem D (Codeforces 828D) - 贪心

    Arkady needs your help again! This time he decided to build his own high-speed Internet exchange poi ...

  5. CodeForces - 93B(贪心+vector<pair<int,double> >+double 的精度操作

    题目链接:http://codeforces.com/problemset/problem/93/B B. End of Exams time limit per test 1 second memo ...

  6. C - Ordering Pizza CodeForces - 867C 贪心 经典

    C - Ordering Pizza CodeForces - 867C C - Ordering Pizza 这个是最难的,一个贪心,很经典,但是我不会,早训结束看了题解才知道怎么贪心的. 这个是先 ...

  7. Codeforces 570C 贪心

    题目:http://codeforces.com/contest/570/problem/C 题意:给你一个字符串,由‘.’和小写字母组成.把两个相邻的‘.’替换成一个‘.’,算一次变换.现在给你一些 ...

  8. Codeforces 732e [贪心][stl乱搞]

    /* 不要低头,不要放弃,不要气馁,不要慌张 题意: 给n个插座,m个电脑.每个插座都有一个电压,每个电脑都有需求电压. 每个插座可以接若干变压器,每个变压器可以使得电压变为x/2上取整. 有无限个变 ...

  9. Codeforces 721D [贪心]

    /* 不要低头,不要放弃,不要气馁,不要慌张. 题意: 给一列数a,可以进行k次操作,每次操作可以选取任意一个数加x或者减x,x是固定的数.求如何才能使得这个数列所有数乘积最小. 思路: 贪心...讨 ...

  10. CodeForces - 424B (贪心算法)

    Megacity Time Limit: 2000MS   Memory Limit: 262144KB   64bit IO Format: %I64d & %I64u Submit Sta ...

随机推荐

  1. python_如何在一个for循环中迭代多个可迭代对象?

    案例: 某班学生期末考试成绩,语文.数学.英语分别存储在3个列表中,同时迭代三个列表.,计算每个学生的总分(并行) 某年级有4个班,某次英语成绩分别记录在4个列表中,依次迭代每个列表,统计全年级高于9 ...

  2. js随机生成验证码及其颜色

    今天迎来了2018年第一场雪,这个美好的日子,总的写点什么纪念一下,在这里写了一个在js中使用Math.random()函数,随机生成四位数的验证码及其验证码换颜色. js代码如下: var arra ...

  3. jquery与js添加子元素

    例如在select中添加option JQuery做法: <select id="myselect" name="myselect"> </s ...

  4. ORACLE数据库链接

    在ORACLE里面,远程数据访问,像查询.更新等可以通过Database Link来实现.数据库连接需要在建立Database Link的两台机子上都运行Oracle Net(以前叫SQL*NET 和 ...

  5. js promise看这篇就够了

    一.背景 大家都知道nodejs很快,为什么会这么快呢,原因就是node采用异步回调的方式来处理需要等待的事件,使得代码会继续往下执行不用在某个地方等待着.但是也有一个不好的地方,当我们有很多回调的时 ...

  6. Git的基本原理与常用命令[二]

    标签(linux): git 笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 git 的四个区域 四种状态 常用命令 git add #加入暂存(索引区) git ...

  7. 解读TCP 四种定时器

    TCP 是提供可靠的传输层,它使用的方法之一就是确认从另一端收到的数据.但是数据和确认都可能会丢失.TCP 通过在发送时设置一个定时器来解决这个问题.如果当定时器溢出时还没收到确认,它就会重传该数据. ...

  8. 使用Filebeat和Logstash集中归档日志

    方 案 Filebeat->Logstash->Files Filebeat->Redis->Logstash->Files Nxlog(Rsyslog.Logstash ...

  9. Django中不返回QuerySets的API -- Django从入门到精通系列教程

    该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. Python及Django学习QQ群:453 ...

  10. maven项目引入sqljdbc4 找不到包的完美 解决方案。

    今天碰到了这个问题,解决了,顺便做一下记录.首先来 重现 一下这个问题,maven install报错,说 找不到这个包,但是其实 我已经安装了. 我们 再来 看看 maven本地仓库里面有 什么,这 ...