日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[NOI2001]炮兵阵地

發布時間:2024/4/15 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [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 PHHP

Sample 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]炮兵阵地的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。