[NOI2001]炮兵阵地
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 PHHPSample Output
6 一開始我是2維的dp #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <iostream> using namespace std; #define N 105 #define M 10005 int can[N],m,n; int f[M][N]; char S1[N]; int st[M]; int num2[M]; int judge1(int x) {if(x&(x<<1)){return 0;}if(x&(x<<2)){return 0;}return 1; } int judge2(int line,int x) {if(can[line]&st[x])return 0;return 1; } int same(int x,int z) {int S=st[x],s2=st[z];if((s2&S)==0){return 1;}return 0; } int num1(int x) {int cnt=0;for(int i=0;x!=0;i++){if(x&1){cnt++;}x=x>>1;}return cnt; } int main() {scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%s",S1);for(int j=1;j<=m;j++){if(S1[j-1]=='H'){can[i]=can[i]|(1<<(j-1));}}}int num=0;for(int i=1;i<(1<<m);i++){if(judge1(i)==1){num2[num]=num1(i);st[num++]=i;}}for(int i=0;i<=num;i++){if(judge2(1,i)==0)continue;f[i][1]=num2[i];}int ans=0;for(int S=0;S<num;S++){if(judge2(2,S)==0)continue;for(int s1=0;s1<num;s1++){if(judge2(1,s1)==0)continue;if(same(s1,S)==1){f[S][2]=max(num2[s1]+num2[S],f[S][2]);}}}for(int i=3;i<=n;i++){for(int S=0;S<num;S++){if(judge2(i,S)==0)continue;for(int s1=0;s1<num;s1++){if(judge2(i-1,s1)==0)continue;if(same(S,s1)==0)continue;for(int s2=0;s2<num;s2++){if(judge2(i-2,s2)==0)continue;if(same(s2,s1)==0)continue;if(same(S,s2)==1){f[S][i]=max(f[s2][i-2]+num2[s1]+num2[S],f[S][i]);ans=max(f[S][i],ans);}}}}}printf("%d\n",ans); } View Code后來我發現——
i-1可能和i-3沖突
所以還是改成3維了
dp[i][line][k]與f[k][line-1][l]有關
所以
#include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <iostream> using namespace std; #define N 105 #define M 1<<11 int can[N],m,n; int f[M][N][M]; char S1[N]; int st[M]; int num2[M]; int judge1(int x) {if(x&(x<<1)){return 0;}if(x&(x<<2)){return 0;}return 1; } int judge2(int line,int x) {if(can[line]&st[x])return 0;return 1; } int same(int x,int z) {int S=st[x],s2=st[z];if((s2&S)==0){return 1;}return 0; } int num1(int x) {int cnt=0;for(int i=0;i<=12;i++){if((x>>i)&1){cnt++;}}return cnt; } int main() {scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%s",S1);for(int j=1;j<=m;j++){if(S1[j-1]=='H'){can[i]=can[i]|(1<<(j-1));}}}int num=0;for(int i=0;i<(1<<m);i++){if(judge1(i)==1){num2[num]=num1(i);st[num++]=i;}}int ans=0;memset(f,-0x3f,sizeof(f));for(int i=0;i<num;i++){if(judge2(1,i)==0)continue;f[i][1][1]=num2[i];f[i][1][0]=num2[i];}for(int S=0;S<num;S++){if(judge2(2,S)==0)continue;for(int s1=0;s1<num;s1++){if(judge2(1,s1)==0)continue;if(same(s1,S)==1){f[S][2][s1]=max(f[s1][1][0]+num2[S],f[S][2][s1]);}}}for(int i=3;i<=n;i++){for(int S=0;S<num;S++){if(judge2(i,S)==0)continue;for(int s1=0;s1<num;s1++){if(judge2(i-1,s1)==0)continue;if(same(S,s1)==0)continue;for(int s2=0;s2<num;s2++){if(judge2(i-2,s2)==0)continue;if(same(s2,s1)==0)continue;if(same(S,s2)==1){f[S][i][s1]=max(f[s1][i-1][s2]+num2[S],f[S][i][s1]);}}}}}for(int i=0;i<num;i++){if(judge2(n,i)==0)continue;for(int j=0;j<num;j++){if(judge2(n-1,j)==0)continue;if(same(i,j)==0)continue;ans=max(ans,f[i][n][j]);}}printf("%d\n",ans); } View Code很好,這就A了么?
顯然并沒有
所以你可以考慮一下開小一點數組,比如你試試一行有多少種情況,據我所知那是小于100的
hhh
#include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <iostream> using namespace std; #define N 105 #define M 1<<11 int can[N],m,n; int f[N][N][N]; char S1[N]; int st[N]; int num2[M]; int judge1(int x) {if(x&(x<<1)){return 0;}if(x&(x<<2)){return 0;}return 1; } int judge2(int line,int x) {if(can[line]&st[x])return 0;return 1; } int same(int x,int z) {int S=st[x],s2=st[z];if((s2&S)==0){return 1;}return 0; } int num1(int x) {int cnt=0;for(int i=0;i<=12;i++){if((x>>i)&1){cnt++;}}return cnt; } int main() {scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%s",S1);for(int j=1;j<=m;j++){if(S1[j-1]=='H'){can[i]=can[i]|(1<<(j-1));}}}int num=0;for(int i=0;i<(1<<m);i++){if(judge1(i)==1){num2[num]=num1(i);st[num++]=i;}}int ans=0;memset(f,-0x3f,sizeof(f));for(int i=0;i<num;i++){if(judge2(1,i)==0)continue;f[i][1][1]=num2[i];f[i][1][0]=num2[i];}for(int S=0;S<num;S++){if(judge2(2,S)==0)continue;for(int s1=0;s1<num;s1++){if(judge2(1,s1)==0)continue;if(same(s1,S)==1){f[S][2][s1]=max(f[s1][1][0]+num2[S],f[S][2][s1]);}}}for(int i=3;i<=n;i++){for(int S=0;S<num;S++){if(judge2(i,S)==0)continue;for(int s1=0;s1<num;s1++){if(judge2(i-1,s1)==0)continue;if(same(S,s1)==0)continue;for(int s2=0;s2<num;s2++){if(judge2(i-2,s2)==0)continue;if(same(s2,s1)==0)continue;if(same(S,s2)==1){f[S][i][s1]=max(f[s1][i-1][s2]+num2[S],f[S][i][s1]);}}}}}for(int i=0;i<num;i++){if(judge2(n,i)==0)continue;for(int j=0;j<num;j++){if(judge2(n-1,j)==0)continue;if(same(i,j)==0)continue;ans=max(ans,f[i][n][j]);}}printf("%d\n",ans); }很好,這就真的A了!
卡了我兩天啊...
?
轉載于:https://www.cnblogs.com/Winniechen/p/6910229.html
總結
以上是生活随笔為你收集整理的[NOI2001]炮兵阵地的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TTL_CMOS_RS232区别
- 下一篇: 51nod 1574 排列转换