题意:给定m个操作和这几种操作所花费的能量,操作的长度n,如果源串能过经过这几种操作转化为目的串,问最多消耗多少能量。
思路:最短路径,也就是bfs+优先队列,不过在记录入队后的元素时要注意,进入队列的元素有可能在进入队列,因为多路径嘛,也就是说,根据最短路径的思想,要及时更新入队的元素,我用的是STL中的priority_queue来操作的,用堆应该快一些吧,记录状态的时候可以根据位运算来实现,减少内存和时间。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#include <cmath>
#include <set>
#include <queue>
#include <vector>
using namespace std;
const int BORDER = (1<<20)-1;
#define MAXN 50
#define INF 0x7ffffff
#define CLR(x,y) memset(x,y,sizeof(x))
#define ADD(x) ((++x)&BORDER)
#define IN(x) scanf("%d",&x)
#define OUT(x) printf("%d\n",x)
#define MIN(m,v) (m)<(v)?(m):(v)
#define MAX(m,v) (m)>(v)?(m):(v)
#define ABS(x) (x>0?x:-x)
struct NODE{
int val;
int step;
}node,t_node;
bool operator<(const NODE& a,const NODE& b)
{
return a.step>b.step;
}
priority_queue<NODE> que;
int tt,n,m,n_word,mmin;
int dist[1<<22],op[MAXN][MAXN],cost[MAXN],origin[MAXN],target[MAXN];
int ans[MAXN];
int init()
{
CLR(dist,127);
CLR(origin,0);
CLR(target,0);
CLR(ans,-1);
return 0;
}
int input()
{
int i,j,tmp;
char str[MAXN];
scanf("%d%d%d",&n,&m,&n_word);
for(i = 0; i < m; ++i)
{
scanf("%s %d",str,&cost[i]);
for(j = 0; j < n; ++j)
{
switch(str[j])
{
case 'N': op[i][j] = 0; break;
case 'F': op[i][j] = 1; break;
case 'S': op[i][j] = 2; break;
case 'C': op[i][j] = 4; break;
}
}
}
for(i = 0; i < n_word; ++i)
{
scanf("%s",str);
for(j = 0; j < n; ++j)
if(str[j] == '1')
origin[i] |= (1<<n-j-1);
scanf("%s",str);
for(j = 0; j < n; ++j)
if(str[j] == '1')
target[i] |= (1<<n-j-1);
}
return 0;
}
int bfs(const int& index)
{
int i,j,tmp,val,oper,k;
/* empty the queue */
while(!que.empty())
que.pop();
/* init queue */
node.val = origin[index];
node.step = 0;
que.push(node);
mmin = INF;
/* while loop */
while(!que.empty())
{
node = que.top();
que.pop();
val = node.val;
if(val == target[index])
{
mmin = MIN(mmin,node.step);
break;
}
for(i = 0; i < m; ++i)
{
tmp = val;
for(j = 0; j < n; ++j)
{
oper = op[i][j];
k = n-j-1;
if(oper&1)
tmp = tmp^(1<<k);
else if(oper&2)
tmp = tmp|(1<<k);
else if(oper&4)
tmp = tmp&(~(1<<k));
}
if(dist[tmp] > node.step+cost[i])
{
dist[tmp] = node.step+cost[i];
t_node.val = tmp;
t_node.step = node.step+cost[i];
que.push(t_node);
}
}
}
if(mmin != INF)
ans[index] = mmin;
return 0;
}
int output()
{
int i,j,tmp;
for(i = 0; i < n_word; ++i)
{
if(i == 0)
{
if(ans[0] == -1)
printf("NP");
else
printf("%d",ans[0]);
continue;
}
if(ans[i] == -1)
printf(" NP");
else
printf(" %d",ans[i]);
}
printf("\n");
return 0;
}
int main()
{
int i,j,tmp;
IN(tt);
while(tt--)
{
init();
input();
for(i = 0; i < n_word; ++i)
{
CLR(dist,127);
bfs(i);
}
output();
}
return 0;
}