状态压缩.种花小游戏

来源:互联网 发布:网易 魔兽对战平台 mac 编辑:程序博客网 时间:2024/04/30 12:34

HLUOJ486. 种花小游戏

状压经典的例题

题目描述

植物大战僵尸这款游戏中,还有个特别有意思的赚钱方式——种花(能长金币的花)。 种出来的金币需要玩家点击才能得到,或者,玩家可以购买一只蜗牛来帮助捡金币。然而,蜗牛爬得
慢是众所周知的。所以,场上有若干金币时,蜗牛总是喜欢以最少的行程来捡走所有的金币。 现在告诉你场上n个金币所在位置的坐标,以及蜗牛所在位置,让你求出蜗牛捡走所有金币的最小行程。

输入格式

第一行一个正整数n,表示金币数量 之后n行,每行两个非负整数x、y,分别表示金币所在位置坐标 最后一行两个正整数x、y表示蜗牛起始位置。

输出格式

一个实数(保留2位小数),表示最短行程
这题就简单的状压,然而由于一个巨坑卡了两个小时,到最后才发现了一个问题。

if((zh&mi(i-1,1))==0) continue;

一开始这句话zh&mi(i-1,1)两边没加括号,然后它居然先算的是mi(i-1,1)==0,得到布尔值再与zh进行&运算,于是我调了1个小时找各种错误。
代码如下:
#include<bits/stdc++.h>
using namespace std;
int x[20],y[20],xs,ys,n,k;
double s[20][20],f[68000][30];
int mi(int num,int sum)
{
if(num==0) return sum;
sum*=2;num--;
return mi(num,sum);
}
int read()
{
bool flag=true;
int num=0;char c=getchar();
for(;c<'0'||c>'9';c=getchar())if(c=='-') flag=false;
for(;c>='0'&&c<='9';c=getchar())
num=(num<<3)+(num<<1)+c-48;
if(flag) return num;
else return -num;
}
void init()
{
n=read();
for(int i=1;i<=n;++i)
x[i]=read(),y[i]=read();
xs=read(),ys=read();
x[0]=xs;y[0]=ys;
for(int i=1;i<=n;++i)for(int j=1;j<=n;++j) s[i][j]=2000000000.0;
for(int i=0;i<=n;++i)
for(int j=i;j<=n;++j)
s[i][j]=s[j][i]=sqrt( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) );
k=mi(n,1);k--;
return;
}
void dp(int zh,int pl)
{
for(int i=1;i<=n;++i)
{
if((zh&mi(i-1,1))==0) continue;
if(f[zh-mi(i-1,1)][i]==1689000000.0) {dp(zh-mi(i-1,1),i);f[zh][pl]=min(f[zh][pl],f[zh-mi(i-1,1)][i]+s[i][pl]);}
else f[zh][pl]=min(f[zh][pl],f[zh-mi(i-1,1)][i]+s[i][pl]);
}
}
int main()
{
init();
for(int i=0;i<=k;++i) for(int j=1;j<=n;++j) f[i][j]=1689000000.0;
for(int i=1;i<=n;++i) f[0][i]=s[0][i];
double ans=2000000000.0;
for(int i=1;i<=n;++i) dp(k-mi(i-1,1),i),ans=min(ans,f[k-mi(i-1,1)][i]);
printf("%.2lf",ans);
return 0;
}

以后还是要注意运算顺序啊。