这是一道好题目啊,放假回头准备练练手的,发现是我弱爆了。。。首先一开始就大致确定好了思路,画了一会,发现优先队列直接贪心就可以的,接下来就敲了,一开始都用了字符串导致一直WA,做了一个下午把,后来发现了错的地方,然后接着TLE,然后看网上说是不要用STL的优先队列,自己写一个小顶堆,然后套了个模板,结果还是TLE,认为自己的模板错了,可是发现跟别人的一致,又弄到了现在,实在找不出哪里有问题,然后看题解了,发现了一篇转化着做的,把字符串转化成二进制的十进制数,这样就直接利用位运算来做,总算是A掉了,去尝试了记忆化搜索,因为转化后有状态标记的,试了几次,发现不行,就放弃了,一天就做了这一道题目。。。
参考了:戳这里
做法还是比较清晰的,画一画再大胆猜测一下,留个纪念,毕竟做了一天,题意说不清楚引用别人的:题目给出nop个操作,由N(什么都不做),S(置1),C(置0),F(反转)等基本操作组成,每一种操作会产生不同的热量。又给出nw组初始字符串和目标字符串,要求出将初始字符串转化成目标字符串至少需要产生的热量;有可能没有解,此时输出“NP”
直接bfs,类似于dfs的暴力枚举一样,队列循环,每一次都去扫一遍nop的所有操作,然后花费小的优先,暴力寻找,找到跳出,找不到就是没有答案的,同时还要标记此状态是否已经出现过了,每一个求答案都得要把状态标记数组清空,前几天因为用了memset总是TLE,坑了许久,这题目还是有点虚的,还好没有被坑
以后做题要提醒自己发现思路了,要先好好想想怎么样做最方便,不然也把自己绕醉了~
typedef struct Node { int val; int ss; friend bool operator<(Node x,Node y) { return x.val > y.val; } }; int n,nop,nw; int make_true[30 + 5],make_false[30 + 5],xo[30 + 5],w[30 + 5]; bool vis[1<<22]; priority_queue<Node > q; void init() { memset(make_true,0,sizeof(make_true)); memset(make_false,0,sizeof(make_false)); memset(xo,0,sizeof(xo)); memset(w,0,sizeof(w)); } bool input() { while(cin>>n>>nop>>nw) { for(int i=0;i<nop;i++) { char s[20 + 5]; scanf("%s %d",&s,&w[i]); for(int j=0;j<n;j++) { make_true[i] <<= 1; make_false[i] <<= 1; xo[i] <<= 1; make_false[i]++; if(s[j] == 'S')make_true[i]++; else if(s[j] == 'F')xo[i]++; else if(s[j] == 'C')make_false[i]--; } } return false; } return true; } int slove(char *s) { int len = strlen(s); int ret = 0; for(int i=0;i<len;i++) { ret <<= 1; if(s[i] == '1')ret++; } return ret; } int bfs(int start,int end) { memset(vis,false,sizeof(vis)); while(!q.empty()) q.pop(); Node s,e; s.val = 0; s.ss = start; q.push(s); while(!q.empty()) { s = q.top(); q.pop(); int pos = s.ss; if(vis[pos])continue; if(pos == end)return s.val; vis[pos] = true; for(int i=0;i<nop;i++) { int tmp = ((pos&make_false[i])|make_true[i])^xo[i]; if(!vis[tmp]) { e.ss = tmp; e.val = s.val + w[i]; q.push(e); } } } return -1; } void cal() { int q = nw; bool flag = false; while(q--) { char start[20 + 5],end[20 + 5]; scanf("%s %s",start,end); if(flag)putchar(' '); else flag = true; int s = slove(start); int e = slove(end); int ans = bfs(s,e); if(ans < 0)printf("NP"); else printf("%d",ans); //cout<<"-->"; } puts(""); } void output() { } int main() { int t; cin>>t; while(t--) { init(); if(input())return 0; cal(); output(); } return 0; }
时间: 2024-10-13 05:34:01