[codevs1647]炮兵阵地
来源:互联网 发布:mysql主键从1开始 编辑:程序博客网 时间:2024/06/06 04:04
乍看这题,差不多理清要枚举上层和上上层……
然而……,1000^3能过?!
然后发现许多状态预处理时就能删掉……统共合理的(没有相邻1)的情况不过100+
于是预处理出前两层的答案
转移时三层枚举
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN = 125 + 50;int dp[MAXN][MAXN][MAXN],num[MAXN];int vis[11];int digit[MAXN],tot,n,m;void init(){ for(int i = 1;i <= 4048;i ++) { int w = 0,cnt = 0; bool flag = true; memset(vis,0,sizeof(vis)); while((1 << w) <= i) { if(i & (1 << w)) { vis[w] = true; cnt ++; if(vis[w - 1] || vis[w - 2]) { flag = false; break; } } w ++; } if(!flag)continue; digit[++ tot] = i; num[tot] = cnt; }}char s[1001];int mp[1001],ans;int main(){ init(); memset(dp,-1,sizeof(dp)); scanf("%d%d",&n,&m); for(int i = 1;i <= n;i ++) { scanf("%s",s); for(int j = 0;j < m;j ++) { if(s[j] == 'H') { mp[i] += (1 << j); } } } for(int i = 1;i <= tot && digit[i] < (1 << m);i ++) { for(int j = 1;j <= tot && digit[j] < (1 << m);j ++) { int tmp1 = digit[i]; int tmp2 = digit[j]; if((!(tmp1 & tmp2)) && (!(tmp1 & mp[2])) && (!(tmp2 & mp[1]))) { dp[2][i][j] = num[i] + num[j]; ans = max(ans,dp[2][i][j]); } } } for(int k = 3;k <= n;k ++) { for(int i = 0;i <= tot && digit[i] < (1 << m);i ++) { if(digit[i] & mp[k - 1])continue; for(int j = 0;j <= tot && digit[j] < (1 << m);j ++) { if(digit[j] & mp[k - 2])continue; if(dp[k - 1][i][j] == -1)continue; //dp[k][0][i] = max(dp[k][0][i],dp[k - 1][i][j]); for(int t = 0;t <= tot && digit[t] < (1 << m);t ++) { if(!(digit[t] & mp[k]) && (!(digit[t] & digit[i])) && (!(digit[t] & digit[j]))) { dp[k][t][i] = max(dp[k][t][i],num[t] + dp[k - 1][i][j]); ans = max(ans,dp[k][t][i]); } } } } } printf("%d",ans); return 0;}
还有一份wwq大佬的代码,预处理略微不同,判断是否有相邻1时更机智
#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int MAXN=100+5;int f[MAXN][100][100],mp[MAXN],sav[100],num[100];char ch[12];int n,m,cnt;bool check(int x){ if((x&(x<<1))||(x&(x<<2))) return 0; return 1;}void read(int& x){ char c; x=0; for(c=getchar();c!='P'&&c!='H';c=getchar()); for(int i=0;c=='P'||c=='H';c=getchar(),++i) if(c=='H') x|=(1<<i);}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) read(mp[i]); for(int i=0;i<1<<m;++i) if(check(i)) { sav[++cnt]=i; for(int j=0;j<m;++j) if(i&(1<<j)) ++num[cnt]; } for(int i=1;i<=cnt;++i) if(!(sav[i]&mp[1])) f[1][i][1]=num[i]; for(int i=2;i<=n;++i) for(int j=1;j<=cnt;++j) { if(sav[j]&mp[i]) continue; for(int k=1;k<=cnt;++k) { if((sav[k]&mp[i-1])||(sav[j]&sav[k])) continue; for(int w=1;w<=cnt;++w) { if((sav[w]&mp[i-2])||(sav[w]&sav[j])||(sav[w]&sav[k])) continue; f[i][j][k]=max(f[i][j][k],f[i-1][k][w]+num[j]); } } } int ans=0; for(int i=1;i<=cnt;++i) { if(mp[n]&sav[i]) continue; for(int j=1;j<=cnt;++j) { if(!(mp[n-1]&sav[j])&&!(sav[i]&sav[j])) ans=max(ans,f[n][i][j]); } } printf("%d",ans); return 0;}
阅读全文
0 0
- [codevs1647]炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- 炮兵阵地
- pku1185炮兵阵地
- poj 1185 炮兵阵地
- POJ 1185 炮兵阵地
- 1185 炮兵阵地
- 炮兵阵地 POJ1185
- 用函数对数组进行初始化,逆置,清空
- codeforces 583B B. Once Again...(LIS)
- 数据存储
- Poj
- linux 下 top 命令的含义
- [codevs1647]炮兵阵地
- CodeForces 868C Qualification Rounds
- caffe中Python层的使用
- 计算机各层网络协议
- 【tensorflow】tensor连接操作concat
- 文件系统(一)
- 对象引用之String
- JZOJ 5406. 【NOIP2017提高A组模拟10.10】Tree
- 剑指offer第16题(合并两个排序的链表)