您的位置:首页 > 其它

codeforces 286 div2

2015-01-19 23:08 363 查看
这场好难啊...div1和div2都没有人ak..手速已经比较渣了,水过两题还能rank300...第三题一开始状态分析的有问题,wa了三发后搞对了,又发现难以优化,看了别人的题解才发现这个优化方法真的很机智。学习了

(突然发现这场前三道题的优化方法,或者说简单解法都和数据量有关...很有意思)

因为太渣只看了前3题

A.Mr. Kitayuta's Gift:点击打开链接

这个题就是给你一串字符串,长度在10以内,让你判断能否加入一个字符来使这成为一个回文串,字符集为小写字母。

因为长度很短,字符集也不大,所以直接暴力枚举每个位置插入一个字符看是否能成为回文串,字符串长度为n,集合大小为26,复杂度为o(26*n^2)。

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

char txt[20],ans[20];

bool judge(){
int len,tmp;
len=strlen(ans);
tmp=len/2;
for(int i=0;i<tmp;i++){
if(ans[i]!=ans[len-1-i]) return false;
}
return true;
}

int main()
{
gets(txt);
int len,tmp,k;
len=strlen(txt);
bool flag;
for(int i=0;i<=len;i++){
for(int j=0;j<26;j++){
for(k=0;k<i;k++){
ans[k]=txt[k];
}
ans[k++]='a'+j;
for(;k<len+1;k++){
ans[k]=txt[k-1];
}

if(judge()){
printf("%s\n",ans);
return 0;
}
}
}
printf("NA\n");
return 0;
}


B. Mr. Kitayuta's Colorful Graph:点击打开链接
这个题就是说,有一张无向图,有n个顶点,边被c种不同的颜色染色(两点之间可能存在多条不同颜色的边),问两点之间有几条单色路径组成的通路。将每一种颜色都分成一个图单独来搜索,dfs的话可以搜出每个点所归属的联通分支,每张图都搜索一遍。复杂度应该是o(c*n),然后对每一个图查询两个点是否属于同一个连通分支。

除此之外还有另外一种快速并且节省空间的方法,就是使用并查集!不需要建图,只需要每次将一条边的两点union一下就可以了。
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

int father[105][105];
int color;

int Find(int x,int c){
if(x== father[c][x]) return x;
return father[c][x]=Find(father[c][x],c);
}

void Union(int a,int b,int c){
int pa=Find(a,c);
int pb=Find(b,c);
if(pa!=pb) father[c][pa]=pb;
}

int main()
{
int n,m,q,a,b,c,u,v;
cin>>n>>m;
for(int i=1;i<105;i++){
for(int j=1;j<105;j++){
father[i][j]=j;
}
}
color=0;
for(int i=0;i<m;i++){
scanf("%d%d%d",&a,&b,&c);
Union(a,b,c);
}

cin>>q;
int ans;
for(int i=0;i<q;i++){
ans=0;
scanf("%d%d",&u,&v);
for(int i=1;i<101;i++){
a=Find(u,i);
b=Find(v,i);
if(a==b) ans++;
}
printf("%d\n",ans);
}
return 0;
}
C.
Mr. Kitayuta, the Treasure Hunter:点击打开链接

对这个题目的分析经历了十分挫折的过程...显然是一个dp,状态分析漏掉了很多内容..过了样例,后面就开始wa。

然后分析对了以后,写了一个未优化的比较搓的代码,如果时限改成2s应该就能过...

看了优化方法确实非常的机智,因为每次跳跃可以选择l-1,l,l+1,这样的话假设第一步跳跃距离为1,那么即使每次只多跳一步,1+2+3+…+250>30000,也就是说,整个过程跳跃距离的变化范围就在d-250~d+250以内,马上将3w*3w的数组优化成了*500的。然后里面还有一些细节值得品味的,比如遇到未初始化的状态直接跳过(通常说明这种状态并不存在),以及对合法性的一些判断。

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define N 30010
int gem
;
int dp
[505];

int main()
{
int n,d,pos,ans;
memset(gem,0,sizeof(gem));
memset(dp,-1,sizeof(dp));
cin>>n>>d;
for(int i=0;i<n;i++){
scanf("%d",&pos);
gem[pos]++;
}
dp[d][250]=gem[d];
ans=gem[d];
int des;
for(int i=d;i<=30000;i++){
for(int j=0;j<=500;j++){
if(dp[i][j]==-1) continue;
des=i+j+d-250;
if(des<=30000){
dp[des][j]=max(dp[des][j],dp[i][j]+gem[des]);
ans=max(ans,dp[des][j]);
}
if(des+1<=30000){
dp[des+1][j+1]=max(dp[des+1][j+1],dp[i][j]+gem[des+1]);
ans=max(ans,dp[des+1][j+1]);
}
if(des-i>1&&des<=30000){
dp[des-1][j-1]=max(dp[des-1][j-1],dp[i][j]+gem[des-1]);
ans=max(ans,dp[des-1][j-1]);
}
}
}
printf("%d\n",ans);
return 0;
}


后续的题琢磨ing...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: