盟军敢死队
2016-03-05 20:48
204 查看
盟军敢死队(cmdo.pas)
【问题描述】
2005年是第二次世界大战胜利60周年,让我们的视线回到战火纷飞的年代……
苏德战争爆发后,苏、美、英3国曾多次商讨在西欧开辟第二战场,共同打击法西斯德国的问题。几经周折,1943年11月,苏、美、英3国首脑在德黑兰会议上最终达成协议。1943年圣诞节前夕,美国正式宣布任命艾森豪威尔将军为盟军最高司令,统一指挥盟军在西欧的登陆作战。1944年初,盟军开始进行登陆作战的准备工作。
盟军开辟第二战场的意图是,在法国西北部登陆,夺取登陆场和港口,保障主力上陆和后勤供应,然后发动攻势占领整个法国西北部地区,并与在法国南部登陆的部队配合,向德国内地进攻,协同苏军最后战胜法西斯德国。盟军在比较了3处较为合适的登陆地点后认为,在诺曼底地区登陆条件最优越。
身经百战的敢死队员们这次接受的是一个看似简单但意义重大的任务:占领诺曼底最大的军火仓库。为了配合即将展开的登陆战,防止德军撤退时摧毁仓库设施,队员们要悄悄的取得仓库的控制权——消灭里面的所有敌人。
显然,敌众我寡,但是对于我们训练有素的队员们来说,这并不是一件困难的事情。
【输入格式】cmdo.in
仓库是一个m*n的矩形区域,每一格用一个字符来描述:“.”代表空地; “#”代表墙或障碍物; “^”, “v”(小写), “<”, “>”四个字符分别表示正向NSWE四个方向看的敌人。敌人总是保持固定不动并朝着一个方向看,从这个方向一直延伸直到边界或障碍物的区域是他的视线范围,如果一个敌人没有在任何人的视线范围之内,敢死队员就可以消灭他。你不能消灭一个正在另一个活着的敌人视线范围内的敌人,否则你就会被发现,后果不堪设想。一个敌人不会成为遮挡视线的障碍物。
输入数据的第一行是用空格分开的两个整数n,m ,分别表示仓库的长和宽。接下来有n行,每行m个字符,是仓库的描述。
【输出格式】cmdo.out
如果能够成功消灭所有敌人,输出消灭所有敌人的不同顺序的数量,否则输出“Impossible”(不含引号)。
【输入样例1】
2 2
>^
#^
【输出样例1】
2
【输入样例2】
1 3
>.<
【输出样例2】
Impossible
【数据规模】
100%的数据中,1<=m,n<=60
90%的数据中,敌人数不超过10
100%的数据中,敌人数不超过15
经典的状压dp,不过隐藏得很深。
对于每个敌人,我们用一个数组LK[][]表示这个敌人能看到的敌人标号(如lk[i][j]若为1则代表i能看到j,当然得先给每个敌人标号),这个预处理一下就OK了,然后就是一道很简单的DP,设f[opt]代表敌人的集合,1表示消灭了,0表示没消灭,对于每个状态,枚举接下来要消灭哪个敌人,然后再判断这个敌人是否被未消灭的敌人看到,如果没看到说明状态合法,由f[opt]转移。每个未被其他敌人看到的敌人的集合的答案为1。
废话不说代码如下#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n,m,t,i,j,k,f[32769];
int a[65][65],lk[65][65],x,y;
char c[65][65];
int main()
{
scanf("%d%d\n",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
cin>>c[i][j];
if (c[i][j]!='#'&&c[i][j]!='.') a[i][j]=++t;
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
if (c[i][j]=='>')
{
for(x=i,y=j+1;y<=m&&c[x][y]!='#';y++)
if (c[x][y]!='.') lk[a[i][j]][a[x][y]]=1;
}
if (c[i][j]=='<')
{
for(x=i,y=j-1;y&&c[x][y]!='#';y--)
if (c[x][y]!='.') lk[a[i][j]][a[x][y]]=1;
}
if (c[i][j]=='^')
{
for(x=i-1,y=j;x&&c[x][y]!='#';x--)
if (c[x][y]!='.') lk[a[i][j]][a[x][y]]=1;
}
if (c[i][j]=='v')
{
for(x=i+1,y=j;x<=n&&c[x][y]!='#';x++)
if (c[x][y]!='.') lk[a[i][j]][a[x][y]]=1;
}
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if (a[i][j])
{
bool fp=1;
for(k=1;k<=t;k++)
if (k!=a[i][j]&&lk[k][a[i][j]]) {fp=0;break;}
if (fp) f[1<<(a[i][j]-1)]=1;
}
int sb=(1<<t)-1;
for(i=0;i<=sb;i++)
{
for(j=1;j<=t;j++)
if (!(i&(1<<(j-1))))
{
bool fp=1;
for(k=1;k<=t;k++)
if (!lk[k][j]||(lk[k][j]&&(i&1<<(k-1)))) continue;
else {fp=0;break;}
if (fp) f[i|(1<<(j-1))]+=f[i];
}
}
if (!f[sb]) cout<<"Impossible";
else cout<<f[sb];
}
【问题描述】
2005年是第二次世界大战胜利60周年,让我们的视线回到战火纷飞的年代……
苏德战争爆发后,苏、美、英3国曾多次商讨在西欧开辟第二战场,共同打击法西斯德国的问题。几经周折,1943年11月,苏、美、英3国首脑在德黑兰会议上最终达成协议。1943年圣诞节前夕,美国正式宣布任命艾森豪威尔将军为盟军最高司令,统一指挥盟军在西欧的登陆作战。1944年初,盟军开始进行登陆作战的准备工作。
盟军开辟第二战场的意图是,在法国西北部登陆,夺取登陆场和港口,保障主力上陆和后勤供应,然后发动攻势占领整个法国西北部地区,并与在法国南部登陆的部队配合,向德国内地进攻,协同苏军最后战胜法西斯德国。盟军在比较了3处较为合适的登陆地点后认为,在诺曼底地区登陆条件最优越。
身经百战的敢死队员们这次接受的是一个看似简单但意义重大的任务:占领诺曼底最大的军火仓库。为了配合即将展开的登陆战,防止德军撤退时摧毁仓库设施,队员们要悄悄的取得仓库的控制权——消灭里面的所有敌人。
显然,敌众我寡,但是对于我们训练有素的队员们来说,这并不是一件困难的事情。
【输入格式】cmdo.in
仓库是一个m*n的矩形区域,每一格用一个字符来描述:“.”代表空地; “#”代表墙或障碍物; “^”, “v”(小写), “<”, “>”四个字符分别表示正向NSWE四个方向看的敌人。敌人总是保持固定不动并朝着一个方向看,从这个方向一直延伸直到边界或障碍物的区域是他的视线范围,如果一个敌人没有在任何人的视线范围之内,敢死队员就可以消灭他。你不能消灭一个正在另一个活着的敌人视线范围内的敌人,否则你就会被发现,后果不堪设想。一个敌人不会成为遮挡视线的障碍物。
输入数据的第一行是用空格分开的两个整数n,m ,分别表示仓库的长和宽。接下来有n行,每行m个字符,是仓库的描述。
【输出格式】cmdo.out
如果能够成功消灭所有敌人,输出消灭所有敌人的不同顺序的数量,否则输出“Impossible”(不含引号)。
【输入样例1】
2 2
>^
#^
【输出样例1】
2
【输入样例2】
1 3
>.<
【输出样例2】
Impossible
【数据规模】
100%的数据中,1<=m,n<=60
90%的数据中,敌人数不超过10
100%的数据中,敌人数不超过15
经典的状压dp,不过隐藏得很深。
对于每个敌人,我们用一个数组LK[][]表示这个敌人能看到的敌人标号(如lk[i][j]若为1则代表i能看到j,当然得先给每个敌人标号),这个预处理一下就OK了,然后就是一道很简单的DP,设f[opt]代表敌人的集合,1表示消灭了,0表示没消灭,对于每个状态,枚举接下来要消灭哪个敌人,然后再判断这个敌人是否被未消灭的敌人看到,如果没看到说明状态合法,由f[opt]转移。每个未被其他敌人看到的敌人的集合的答案为1。
废话不说代码如下#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n,m,t,i,j,k,f[32769];
int a[65][65],lk[65][65],x,y;
char c[65][65];
int main()
{
scanf("%d%d\n",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
cin>>c[i][j];
if (c[i][j]!='#'&&c[i][j]!='.') a[i][j]=++t;
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
if (c[i][j]=='>')
{
for(x=i,y=j+1;y<=m&&c[x][y]!='#';y++)
if (c[x][y]!='.') lk[a[i][j]][a[x][y]]=1;
}
if (c[i][j]=='<')
{
for(x=i,y=j-1;y&&c[x][y]!='#';y--)
if (c[x][y]!='.') lk[a[i][j]][a[x][y]]=1;
}
if (c[i][j]=='^')
{
for(x=i-1,y=j;x&&c[x][y]!='#';x--)
if (c[x][y]!='.') lk[a[i][j]][a[x][y]]=1;
}
if (c[i][j]=='v')
{
for(x=i+1,y=j;x<=n&&c[x][y]!='#';x++)
if (c[x][y]!='.') lk[a[i][j]][a[x][y]]=1;
}
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if (a[i][j])
{
bool fp=1;
for(k=1;k<=t;k++)
if (k!=a[i][j]&&lk[k][a[i][j]]) {fp=0;break;}
if (fp) f[1<<(a[i][j]-1)]=1;
}
int sb=(1<<t)-1;
for(i=0;i<=sb;i++)
{
for(j=1;j<=t;j++)
if (!(i&(1<<(j-1))))
{
bool fp=1;
for(k=1;k<=t;k++)
if (!lk[k][j]||(lk[k][j]&&(i&1<<(k-1)))) continue;
else {fp=0;break;}
if (fp) f[i|(1<<(j-1))]+=f[i];
}
}
if (!f[sb]) cout<<"Impossible";
else cout<<f[sb];
}
相关文章推荐
- 三维坐标旋转矩阵
- BZOJ 3875: [Ahoi2014]骑士游戏
- Java堆内存
- win7下Trim启用的验证方法
- 微信红包接口API实现(php版)
- “老子化胡”和白马寺焚经
- 本次孩子流感总结
- Android实现后台长期监听时间变化
- 《信息资源管理》之前五章细化总结
- Spring连接mysql数据库错误:Cannot load JDBC driver class '${driver}'
- AS导入外部项目
- 找工作——JVM内存管理
- ZOJ-1045
- JAVA常用基础知识点[继承,抽象,接口,静态,枚举,反射,泛型,多线程...]
- jQuery——语法
- location.replace与location.href,location.reload的区别
- 1104. Sum of Number Segments (20)
- lamp的403问题
- .使用malloc开辟一个3*4的二维数组,并将内容初始化为0-11
- 谈谈iOS开发中的frame、bounds和center