http://ac.jobdu.com/problem.php?pid=1029魔咒词典
题目当中每个魔咒用一对括号[ ] 来包含,测试数据在一对括号当中会有空格,这个小问题导致一直是WA,应该首先把一行字符串都读进来,然后在分别提取出魔咒和对应的功能。
方法一:
//使用双map来实现
#include<iostream>
#include<map>
#include<cstdio>
#include<string>
using namespace std;
map<string,string>map_magic,map_funtion;
int main(void)
{
int n,k;
string str1,str2,str,temp_str;
map_magic.clear();
map_funtion.clear();
while(getline(cin,temp_str))
{
if(temp_str=="@END@")
break;
k=temp_str.find("]");
str1=temp_str.substr(0,k+1);
str2=temp_str.substr(k+2,temp_str.size()-k-2);
map_magic[str1]=str2;
map_funtion[str2]=str1;
}
scanf("%d",&n);
getchar();
while(n--)
{
getline(cin,str);
if(str[0]=='[')
{
if(map_magic.count(str))
cout<<map_magic[str]<<endl; //由魔咒来选择功能
else
cout<<"what?"<<endl;
}
else
{
if(map_funtion.count(str))
{
temp_str=map_funtion[str]; //由功能来选择魔咒
cout<<temp_str.substr(1,temp_str.size()-2)<<endl;
}
else
cout<<"what?"<<endl;
}
}
return 0;
}
方法二:
//字符串哈希的时间最快,只需要10 MS
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 100100
#define M 100100
const char *end = "@END@";
char word[N][25], expr[N][85];
int magic[M], funtion[M];
unsigned int bkdrHash(char *str)
{
unsigned int seed = 131;
unsigned int hash = 0;
while(*str)
{
hash = hash * seed + *str++;
}
return (hash & 0x7FFFFFFF) % M;
}
int setPos(int idx, int arr[])
{
int i = 1;
while(arr[idx]) //哈希地址冲突的时候
{
idx = (idx + i * i) % M; //处理哈希冲突的方法,二次探测再散列
i++;
}
return idx;
}
int getPos(int idx, int arr[], int type, char *str)
{
int i = 1, k = 0;
while(arr[idx])
{
if(type == 0 && strcmp(word[arr[idx]], str) == 0)
{
k = magic[idx]; //找到魔咒在字典中的位置
break;
}
else if(type && strcmp(expr[arr[idx]], str) == 0)
{
k = funtion[idx]; //找到功能在字典中的位置
break;
}
else
{
idx = (idx + i * i) % M;
i++;
}
}
return k;
}
int main(void)
{
char str[128];
int i, j, k, n;
k = 1;
memset(magic, 0, sizeof(magic));
memset(funtion, 0, sizeof(funtion));
while(gets(str))
{
if(strcmp(str, end) == 0)
break;
for(i=0;str[i]!= ']';i++)
word[k][i]=str[i]; //保存魔咒
word[k][i]=str[i];
i++;
word[k][i++]='\0';
j = setPos(bkdrHash(word[k]), magic);
magic[j] = k;
j = 0;
for(;str[i]!='\0';i++)
expr[k][j++]=str[i]; //保存功能
expr[k][j]='\0';
j = setPos(bkdrHash(expr[k]), funtion);
funtion[j] = k;
k++;
}
scanf("%d", &n);
getchar();
while(n--)
{
gets(str);
if(str[0] == '[')
{
j = getPos(bkdrHash(str), magic, 0, str);
if(j) //查询成功
puts(expr[j]);
else //查询失败
printf("what?\n");
}
else
{
j = getPos(bkdrHash(str), funtion, 1, str);
if(j)
{
k = strlen(word[j]);
for(i = 1; i < k-1; i++)
printf("%c", word[j][i]);
printf("\n");
}
else
printf("what?\n");
}
}
return 0;
}
方法三:
//二分查找
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstdio>
#include<string>
using namespace std;
struct Word
{
string magic;
string funtion;
}word;
vector<Word> dic1,dic2;
int my_binary_search(int low, int high,string key,int i)
{
int mid;
if(i==1) //查找魔咒
{
while(low<=high)
{
mid=(low+high)>>1;
if(key<dic1[mid].magic)
high=mid-1;
else if(key==dic1[mid].magic)
return mid;
else
low=mid+1;
}
}
else if(i==2) //查找功能
{
while(low<=high)
{
mid=(low+high)>>1;
if(key<dic2[mid].funtion)
high=mid-1;
else if(key==dic2[mid].funtion)
return mid;
else
low=mid+1;
}
}
return -1; //查找失败
}
bool cmp1(const Word &a,const Word &b)
{
return a.magic<b.magic;
}
bool cmp2(const Word &a,const Word &b)
{
return a.funtion<b.funtion;
}
int main(void)
{
int n,k;
string str,temp_str;
while(getline(cin,temp_str))
{
if(temp_str=="@END@")
break;
k=temp_str.find("]");
word.magic=temp_str.substr(0,k+1);
word.funtion=temp_str.substr(k+2,temp_str.size()-k-2);
dic1.push_back(word);
dic2.push_back(word);
}
sort(dic1.begin(), dic1.end(), cmp1); //按照魔咒的字典序进行排序
sort(dic2.begin(), dic2.end(), cmp2); //按照功能的字典序进行排序
scanf("%d",&n);
getchar();
vector<Word>::iterator iter; //vector的迭代器
while(n--)
{
getline(cin,str);
if(str[0]=='[') //由魔咒来选择功能
{
k=my_binary_search(0, dic1.size()-1,str,1);
if(k!=-1)
cout<<dic1[k].funtion<<endl;
else
cout<<"what?"<<endl;
}
else
{
k=my_binary_search(0, dic2.size()-1 ,str,2);
if(k!=-1)
{
temp_str=dic2[k].magic;
cout<<temp_str.substr(1,temp_str.size()-2)<<endl;
}
else
cout<<"what?"<<endl;
}
}
return 0;
}
方法四: (可能会导致超时)
//使用一个map来实现,反过来用迭代器查询
#include<iostream>
#include<map>
#include<cstdio>
#include<string>
using namespace std;
map<string,string>map_magic;
int main(void)
{
int n,k;
string str1,str2,str,temp_str;
map_magic.clear();
while(getline(cin,temp_str))
{
if(temp_str=="@END@")
break;
k=temp_str.find("]");
str1=temp_str.substr(0,k+1);
str2=temp_str.substr(k+2,temp_str.size()-k-2);
map_magic[str1]=str2;
}
scanf("%d",&n);
getchar();
map<string,string>::iterator iter; //map的迭代器
while(n--)
{
getline(cin,str);
if(str[0]=='[')
{
if(map_magic.count(str))
cout<<map_magic[str]<<endl; //由魔咒来选择功能
else
cout<<"what?"<<endl;
}
else
{
for(iter=map_magic.begin();iter!=map_magic.end();iter++)
{
if((*iter).second==str)
{
temp_str=(*iter).first;
cout<<temp_str.substr(1,temp_str.size()-2)<<endl;
break;
}
}
if(iter==map_magic.end())
cout<<"what?"<<endl;
}
}
return 0;
}
http://ac.jobdu.com/problem.php?id=1030毕业bg
/*
题目实质是01背包问题,不过加了几方面的限制
将bg当作物品,离开时间当作重量,快乐度当作价值,则与01背包不同的是物品放入的顺序是有先后顺序的
所以需要排序
*/
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
#include<memory.h>
struct Node
{
int happy;
int last;
int time;
}node[31];
bool cmp(const Node &a,const Node &b)
{
return a.time<b.time;
}
int dp[1000];
int ZeroOnePack(int n)
{
int i,j,max=-1,p;
memset(dp,0,sizeof(dp));
for(i=0;i<n;i++) //动态规划
{
if(node[i].time>max)
max=node[i].time;
for(j=node[i].time;j>=node[i].last;j--) //j表示背包的大小,从最后离开的时间到持续时间
dp[j] = dp[j]>dp[j-node[i].last]+node[i].happy? dp[j]:dp[j-node[i].last]+node[i].happy;
}
p=-1;
for(i=1;i<=max;i++)
{
if(dp[i]>p)
p=dp[i];
}
return p;
}
int main(void)
{
int i,n;
while(scanf("%d",&n)!=EOF)
{
if(n<0)
break;
for(i=0;i<n;i++)
scanf("%d %d %d",&node[i].happy,&node[i].last,&node[i].time);
sort(node,node+n,cmp); //按最后离开的时间从小到大排序
printf("%d\n",ZeroOnePack(n));
}
return 0;
}