Corn Fields POJ - 3254 && 炮兵阵地 POJ - 1185

第一个题题目链接: POJ - 3254

第二个题题目链接:POJ - 1185

第一个题的题目大意:给你一个n*m的01矩阵,然后让你安排奶牛,只有为1的地方能安置奶牛,0的地方不能安置奶牛。当在一个为1的地方安置奶牛的时候,这个奶牛的四周都不能防止奶牛,会起冲突。然后问你一共有多少种安置方案。

具体思路:我们把每一行按照二进制压缩,然后每一次枚举合法的状态,看是否能安置上奶牛,然后枚举当前一行的时候,判断是否冲突就好了。然后最终计算答案的时候累加最后一行为某一个合法状态时的方案数。

AC代码:

 1 //dp[i][j]代表当前第i行为j时候的合法数。
 2 #include<iostream>
 3 #include<stdio.h>
 4 #include<cmath>
 5 #include<string>
 6 #include<cstring>
 7 #include<algorithm>
 8 using namespace std;
 9 # define ll long long
10 # define inf 0x3f3f3f3f
11 const int maxn = 5e3+100;
12 const int mod  = 1e9;
13 int dp[20][maxn];
14 int a[20][20];
15 int n,m;
16 bool check(int t1,int t2)
17 {
18     if((((t2<<1)&t2)==0)&&(((t2>>1)&t2)==0))
19     {
20         for(int j=0; j<m; j++){
21             if(((t2&(1<<j))&&a[t1][j])||(!(t2&(1<<j))))
22                 continue;
23             else
24                 return false;
25         }
26         return true;
27     }
28     else
29         return false;
30 }
31 int main()
32 {
33     scanf("%d %d",&n,&m);
34     for(int i=0; i<n; i++)
35     {
36         for(int j=0; j<m; j++)
37         {
38             scanf("%d",&a[i][j]);
39         }
40     }
41     int maxstate=(1<<m)-1;
42     for(int i=0; i<n; i++)
43     {
44         if(i==0)
45         {
46             for(int j=0; j<=maxstate; j++)
47             {
48                 if(check(i,j))
49                     dp[i][j]++;
50             }
51         }
52         else
53         {
54             for(int j=0; j<=maxstate; j++)
55             {
56                 for(int k=0; k<=maxstate; k++)
57                 {
58                     if(check(i,k)&&((j&k)==0))
59                     {
60                         dp[i][k]+=dp[i-1][j];
61                     }
62                 }
63             }
64         }
65     }
66 //    for(int i=0;i<=maxstate;i++){
67 //    cout<<i<<" "<<dp[0][i]<<endl;
68 //    }
69     ll sum=0;
70     for(int i=0; i<=maxstate; i++)
71     {
72         sum=(sum+dp[n-1][i])%mod;
73     }
74     printf("%lld\n",sum);
75     return 0;
76 }

第二个题题目大意:中文,和上一个题不同的是这个题求的是最大的合法状态。

具体思路:这个题的难度比上一个题的难度增加了一点,上一个题dp[i][j]表示第i行选j这个状态时的合法数。但是这个题需要判断和上两行的关系。所以我们开一个三维数组。

dp[i][j][k]代表第i行选择j状态,第i-1行选k这个状态时的合法数。然后求一个最大值就好了。

具体判断的时候,如果当前的这一行和sto[i],a[i]&sto[j]==sto[j]的时候,就可以了。

注意需要先预处理出合法的状态,否则会爆内存,因为是个三维空间。

AC代码:

  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<cmath>
  4 #include<string>
  5 #include<algorithm>
  6 #include<vector>
  7 #include<vector>
  8 using namespace std;
  9 # define ll long long
 10 # define inf 0x3f3f3f3f
 11 const int maxn = 2e2+100;
 12 const int mod  = 1e9;
 13 int dp[100+10][maxn][maxn];
 14 int a[200];
 15 char str[100+100][20];
 16 int sto[maxn],num[maxn];
 17 int n,m;
 18 bool check(int t)
 19 {
 20     if(((t<<1)&t)||((t>>1)&t)||((t<<2)&t)||((t>>2)&t))
 21         return false ;
 22     return true;
 23 }
 24 int cal(int t)
 25 {
 26     int ans=0;
 27     while(t)
 28     {
 29         ans+=(t&1);
 30         t>>=1;
 31     }
 32     return ans;
 33 }
 34 int main()
 35 {
 36     scanf("%d %d",&n,&m);
 37     for(int i=0; i<n; i++)
 38     {
 39         scanf("%s",str[i]);
 40         for(int j=0; j<m; j++)
 41         {
 42             a[i]<<=1;
 43             a[i]|=(str[i][j]==‘P‘?1:0);
 44         }
 45     }
 46     int cnt=0;
 47     int maxstate=(1<<m)-1;
 48     for(int i=0; i<=maxstate; i++)
 49     {
 50         if(check(i))
 51         {
 52             sto[++cnt]=i;
 53             num[cnt]=cal(i);
 54         }
 55     }
 56     int maxx=0;
 57     for(int i=0; i<n; i++)
 58     {
 59         if(i==0)
 60         {
 61             for(int j=1; j<=cnt; j++)
 62             {
 63                 if((a[i]&sto[j])!=sto[j])continue;
 64                     dp[i][j][0]=max(dp[i][j][0],num[j]);
 65                     maxx=max(maxx,dp[i][j][0]);
 66             }
 67         }
 68         else if(i==1)
 69         {
 70             for(int j=1; j<=cnt; j++)
 71             {
 72                 if((sto[j]&a[i])!=sto[j])continue;
 73                 for(int k=1; k<=cnt; k++)
 74                 {
 75                     if((sto[k]&a[i-1])!=sto[k])continue;
 76                     if((sto[j]&sto[k])!=0)continue;
 77                     dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][0]+num[j]);
 78                     maxx=max(maxx,dp[i][j][k]);
 79                 }
 80             }
 81         }
 82         else
 83         {
 84             for(int j=1; j<=cnt; j++)
 85             {
 86                 if((sto[j]&a[i])!=sto[j])
 87                     continue;
 88                 for(int k=1; k<=cnt; k++)
 89                 {
 90                     if((sto[k]&a[i-1])!=sto[k]||(sto[k]&sto[j])!=0)
 91                         continue;
 92                     for(int L=1; L<=cnt; L++)
 93                     {
 94                         if((sto[L]&a[i-2])!=sto[L])
 95                             continue;
 96                         if((sto[j]&sto[L])!=0||(sto[k]&sto[L])!=0)
 97                             continue;
 98                         dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][L]+num[j]);
 99                         maxx=max(maxx,dp[i][j][k]);
100                     }
101                 }
102             }
103         }
104     }
105     printf("%d\n",maxx);
106 }

原文地址:https://www.cnblogs.com/letlifestop/p/10807760.html

时间: 2024-10-22 01:44:17

Corn Fields POJ - 3254 && 炮兵阵地 POJ - 1185的相关文章

炮兵阵地 - POJ 1185(状态压缩)

分析:先枚举出来所有的合法状态(当N=10的时候合法状态最多也就60种),用当前状态匹配上一行和上上一行的状态去匹配,看是否可以.....复杂度100*60*60*60,也可以接受. 代码如下: ========================================================================================================================= #include<stdio.h> #include<

炮兵阵地 POJ 1185

n*m P 和 M P可以放人 M不行 人不能相互打到 问最多可以放多少人 #include<stdio.h> #include<algorithm> #include<string.h> #include<math.h> #include<map> using namespace std; #define MAXN 1<<10 char z[105][15]; int x[105]; int dp[105][200][200]; i

POJ 3254 Corn Fields 状态压缩DP (C++/Java)

http://poj.org/problem?id=3254 题目大意: 一个农民有n行m列的地方,每个格子用1代表可以种草地,而0不可以.放牛只能在有草地的,但是相邻的草地不能同时放牛, 问总共有多少种方法. 思路: 状态压缩的DP. 可以用二进制数字来表示放牧情况并判断该状态是否满足条件. 这题的限制条件有两个: 1.草地限制. 2.相邻限制. 对于草地限制,因为输入的时候1是可以种草地的. 以"11110"草地分析,就只有最后一个是不可以种草的.取反后得00001  .(为啥取反

POJ 1185 炮兵阵地 状压dp

http://poj.org/problem?id=1185 经典题目不必多说,直接贴代码. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 int n, m, cnt, size; 7 int a[110], st[70], ct[70]; 8 char str[15]; 9 int f[110][70][70]; 10 void init(

POJ 3254 Corn Fields (状压DP)

题意:一个n*m的矩阵,每个格子是0或者1,1表示土壤肥沃可以种植草地,0则不可以.在种草地的格子可以放牛,但边相邻的两个格子不允许同时放牛,问总共有多少种放牛的方法?(不放牛也算一种情况) 思路:就是POJ 1185 炮兵阵地 的弱化版,炮兵那题相当于间隔两行,这里是间隔一行,减少一维坐标就可 //192 KB 32 ms C++ 1221 B #include<cstdio> #include<cstring> #include<algorithm> #includ

poj 3254 Corn Fields ,状态压缩DP

题目链接 题意: 一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛,即牛与牛不能相邻.问有多少种放牛方案(一头牛都不放也是一种方案) state[i] 表示对于一行,保证不相邻的方案 状态:dp[i][ state[j] ]  在状态为state[j]时,到第i行符合条件的可以放牛的方案数 状态转移:dp[i][ state[j] ] =Sigma dp[i-1][state'] (state'为符合条

POJ 3254. Corn Fields 状态压缩DP (入门级)

Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9806   Accepted: 5185 Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yumm

【POJ 3254】 Corn Fields(状压DP)

[POJ 3254] Corn Fields(状压DP) Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10891   Accepted: 5705 Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parce

POJ 1185 炮兵阵地(动态规划)

炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 19152   Accepted: 7417 Description 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图.在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队):一支炮兵部队在地图上的攻击