zoukankan      html  css  js  c++  java
  • POJ 1185:炮兵阵地

    炮兵阵地
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 21366   Accepted: 8280

    Description

    司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示: 

    如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。 
    现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。 

    Input

    第一行包含两个由空格分割开的正整数,分别表示N和M; 
    接下来的N行,每一行含有连续的M个字符('P'或者'H'),中间没有空格。按顺序表示地图中每一行的数据。N <= 100;M <= 10。

    Output

    仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。

    Sample Input

    5 4
    PHPP
    PPHH
    PPPP
    PHPP
    PHHP

    Sample Output

    6

    这道状态DP折磨了我相当久的时间,做的时候又花了一个下午找WA原因在哪。

    首先,自己做麻烦的第一点在于 a&b 两个十进制的数本身就可以判断两列是否有炮兵对打,而不用像我一开始想象的把十进制转成二进制,再用二进制进行判断,这个已经帮你弄好了。

    第二点,本身状态也没有那么多。最多是1024个,再加上用if((i&i<<1)||(i&i<<2)) (这个判断简直了)之后就剩了大概六十个左右好像是。所以将这些合理的状态记录下来,这样的思路就能够想到了。

    第三点,判断状态 哪一行是属于第几个状态,这点也很好。

    剩下的就是状态dp自己的事了,什么这一行的值只和前两行有关什么的。

    总之,这道题真的很好,很值得琢磨。

    代码:

    #include <iostream>
    #include <vector>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #pragma warning(disable:4996)
    using namespace std;
    
    int hang[110];//hang[i]表示第i行的初始状态
    int state[80];//
    int solider[80];
    int dp[110][80][80];
    int row,col,i,j,k,h,he;
    char pb_state[15];
    
    int main()
    {
    	cin>>row>>col;
    
    	memset(hang,0,sizeof(hang));
    	memset(dp,0,sizeof(dp));
    	memset(solider,0,sizeof(solider));
    	memset(state,0,sizeof(state));
    
    	for(i=1;i<=row;i++)
    	{
    		cin>>pb_state;
    		for(j=0; j<col; j++)
    			if(pb_state[j]=='H') hang[i]+=1<<j; 
    	}
    
    	he=1;
    	for(i=0;i<(1<<col);i++)
    	{
    		if((i&i<<1)||(i&i<<2)) continue;
    		state[he]=i;
    		int temp=i,num=0;
    		while(temp)
    		{
    			num += temp&1;
    			temp=temp>>1;
    		}
    		solider[he]=num;
    		he++;
    	}
    	for(i=1;i<he;i++)
    	{
    		if(state[i]&hang[1])continue;
    		dp[1][i][0]= solider[i];
    	}
    	for(i=1;i<he;i++)
    	{
    		if(state[i]&hang[2])continue;
    		for(j=1;j<he;j++)
    		{
    			if(state[i]&state[j])continue;
    			if(state[j]&hang[1]) continue;
    			dp[2][i][j]=max(dp[2][i][j],dp[1][j][0]+solider[i]);
    		}
    	}
    	for(h=3;h<=row;h++)
    	{
    		for(i=1;i<he;i++)//
    		{
    			if(state[i]&hang[h])continue;
    			for(j=1;j<he;j++)
    			{
    				if(state[j]&hang[h-1])continue;
    				if(state[j]&state[i])continue;
    				for(k=1;k<he;k++)
    				{
    					if(state[k]&hang[h-2])continue;
    					if(state[k]&state[i])continue;
    					if(state[k]&state[j])continue;
    
    					dp[h][i][j]=max(dp[h][i][j],dp[h-1][j][k]+solider[i]);
    				}
    			}
    		}
    	}
    	int ans=0;
    	for(i=1;i<he;i++)
    		for(j=0;j<he;j++)//!!!注意啊,这里一定是从0开始的,因为之前设置好的就是0啊。。。。。。。。。。。。。。。。。。
    			ans=max(ans,dp[row][i][j]);
    	cout<<ans<<endl;
    	//system("pause");
    	return 0;
    }


    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    [转]几个开源的.net界面控件
    电脑上设置对眼睛友好的绿豆沙色
    [转] C# 绘制报表,使用Graphics.DrawString 方法
    Excel 绘制图表,如何显示横轴的数据范围
    [转] C#中绘制矢量图形
    Chapter 3 Protecting the Data(3):创建和使用数据库角色
    续x奇数倍(n+2*x)暴力算法是冠军的算法结合数量
    新秀学习SSH(十四)——Spring集装箱AOP其原理——动态代理
    中国是大数据的人工智能的发源地
    采用shell脚本统计代码的行数
  • 原文地址:https://www.cnblogs.com/lightspeedsmallson/p/4785833.html
Copyright © 2011-2022 走看看