最短Hamilton路径
题目描述
给定一张 n(n \leq 20)(n≤20) 个点的带权无向图,点从0 \sim n-10∼n−1标号,求起点 0 到终点 n-1 的最短Hamilton路径。 Hamilton路径的定义是从 0 到 n-1 不重不漏地经过每个点恰好一次。
输入描述:
第一行一个整数n。
接下来n行每行n个整数,其中第i行第j个整数表示点i到j的距离(一个不超过10^710
7
的正整数,记为a[i,j])。
对于任意的x,y,z,数据保证 a[x,x]=0,a[x,y]=a[y,x] 并且a[x,y]+a[y,z] \geq a[x,z]a[x,y]+a[y,z]≥a[x,z]。
输出描述:
一个整数,表示最短Hamilton路径的长度。
示例1
输入
4
0 2 1 3
2 0 2 1
1 2 0 1
3 1 1 0
输出
4
说明
从0到3的Hamilton路径有两条,0-1-2-3和0-2-1-3。前者的长度为2+2+1=5,后者的长度为1+2+1=4
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=20,M=1<<N;
int f[M][N],w[N][N];//w表示的是无权图
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
cin>>w[i][j];
memset(f,0x3f,sizeof(f));//因为要求最小值,所以初始化为无穷大
f[1][0]=0;//因为零是起点,所以f[1][0]=0;
for(int i=0;i<1<<n;i++)//i表示所有的情况
for(int j=0;j<n;j++)//j表示走到哪一个点
if(i>>j&1)
for(int k=0;k<n;k++)//k表示走到j这个点之前,以k为终点的最短距离
if(i>>k&1)
f[i][j]=min(f[i][j],f[i-(1<<j)][k]+w[k][j]);//更新最短距离
cout<<f[(1<<n)-1][n-1]<<endl;//表示所有点都走过了,且终点是n-1的最短距离
//位运算的优先级低于'+'-'所以有必要的情况下要打括号
return 0;
}
作者:灰之魔女
链接:https://www.acwing.com/solution/content/18533/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
起床困难综合症
题目描述
21 世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳。作为一名青春阳光好少年,atm 一直坚持与起床困难综合症作斗争。通过研究相关文献,他找到了该病的发病原因:在深邃的太平洋海底中,出现了一条名为 drd 的巨龙,它掌握着睡眠之精髓,能随意延长大家的睡眠时间。正是由于 drd 的活动,起床困难综合症愈演愈烈,以惊人的速度在世界上传播。为了彻底消灭这种病,atm 决定前往海底,消灭这条恶龙。
历经千辛万苦,atm 终于来到了 drd 所在的地方,准备与其展开艰苦卓绝的战斗。drd 有着十分特殊的技能,他的防御战线能够使用一定的运算来改变他受到的伤害。具体说来,drd 的防御战线由 𝑛 扇防御门组成。每扇防御门包括一个运算 op 和一个参数 𝑡,其中运算一定是 OR,XOR,AND 中的一种,参数则一定为非负整数。如果还未通过防御门时攻击力为 𝑥 ,则其通过这扇防御门后攻击力将变为 𝑥 op 𝑡 。最终drd 受到的伤害为对方初始攻击力 𝑥 依次经过所有 𝒏 扇防御门后转变得到的攻击力。
由于atm 水平有限,他的初始攻击力只能为 0 到 𝑚 之间的一个整数(即他的初始攻击力只能在 0, 1, … , 𝑚 中任选,但在通过防御门之后的攻击力不受 𝑚 的限制)。为了节省体力,他希望通过选择合适的初始攻击力使得他的攻击能让 drd受到最大的伤害,请你帮他计算一下,他的一次攻击最多能使 drd 受到多少伤害。
输入描述:
第 1 行包含2 个整数,依次为 𝑛, 𝑚 ,表示drd 有 𝑛 扇防御门,atm 的初始攻击力为 0 到 𝑚 之间的整数。
接下来 𝑛 行,依次表示每一扇防御门。每行包括一个字符串 op 和一个非负整数 𝑡,两者由一个空格隔开,且 op 在前, 𝑡 在后,op 表示该防御门所对应的操作,𝑡 表示对应的参数。
输出描述:
输出一行一个整数,表示atm 的一次攻击最多使 drd 受到多少伤害。
示例1
输入
3 10
AND 5
OR 6
XOR 7
输出
1
说明
atm 可以选择的初始攻击力为 0,1, … ,10。
假设初始攻击力为 4,最终攻击力经过了如下计算
4 AND 5 = 4
4 OR 6 = 6
6 XOR 7 = 1
类似的,我们可以计算出初始攻击力为 1,3,5,7,9 时最终攻击力为 0,初始攻击力为 0,2,4,6,8,10 时最终攻击力为 1,因此atm 的一次攻击最多使 drd 受到的伤害值为 1。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m;
void solved()
{
bitset<40>one;
bitset<40>zero;
one.set();//把二进制位都置成1
zero.reset();//把二进制位都置成0
cin>>n>>m;
for(int i=1;i<=n;i++)
{
string s;
int x;
cin>>s>>x;
if(s[0]=='O')one|=x,zero|=x;
if(s[0]=='X')one^=x,zero^=x;
if(s[0]=='A')one&=x,zero&=x;
}
ll ans=0;
for(int i=29;i>=0;i--){
if(zero[i]==1)ans+=(1<<i);
else if(one[i]==1&&(1<<i)<=m)ans+=(1<<i);
}
cout<<ans<<endl;
}
int main()
{
solved();
return 0;
}