思路:模拟,set记录一下。
#include<set> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; set<int>se; int n,k,x,ans; int main(){ freopen("del.in","r",stdin); freopen("del.out","w",stdout); scanf("%d%d",&n,&k); for(int i=1;i<=n;i++){ scanf("%d",&x); if(se.find(x)!=se.end()) k--; else{ se.insert(x); ans++; } } if(k<=0) cout<<ans<<endl; else cout<<ans-k<<endl; }
思路:搜索
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #include <cstdlib> using namespace std; int board[10][10], isKing[10][10]; int dir[4][2] = {{1, 1}, {1, -1}, {-1, 1}, {-1, -1}}; int best_deep; vector<int> w; vector<int> ways; void dfs(int step, int x, int y, int isKing) { w.push_back(x * 10 + y); if (step > best_deep) { best_deep = step; ways.clear(); ways.push_back(w[0]); } else if (step > 1 && step == best_deep) { ways.push_back(w[0]); } int dis_limit = isKing ? 9 : 2; for (int d = 0; d < 4; d++) { bool pass = false; int passx = 0, passy = 0; for (int dis = 1; dis <= dis_limit; dis++) { int nxtX = x + dis * dir[d][0]; int nxtY = y + dis * dir[d][1]; if (!(0 <= nxtX && nxtX < 10 && 0 <= nxtY && nxtY < 10)) break; if (board[nxtX][nxtY] == 1 || board[nxtX][nxtY] == 3) break; if (pass && board[nxtX][nxtY] == 2) break; if (board[nxtX][nxtY] == 2) { pass = true; passx = nxtX; passy = nxtY; } else { if (!pass) continue; board[passx][passy] = 3; dfs(step + 1, nxtX, nxtY, isKing); board[passx][passy] = 2; } } } w.pop_back(); } bool getAvailable() { ways.clear(); w.clear(); best_deep = 1; for (int curX = 0; curX < 10; curX++) for (int curY = 0; curY < 10; curY++) if (board[curX][curY] == 1) dfs(1, curX, curY, isKing[curX][curY]); if (best_deep == 1) { for (int curX = 0; curX < 10; curX++) for (int curY = 0; curY < 10; curY++) if (board[curX][curY] == 1) { if (isKing[curX][curY]) { for (int x = curX + 1, y = curY + 1; 0 <= x && x < 10 && 0 <= y && y < 10; x++, y++) if (!board[x][y]) ways.push_back(curX * 10 + curY); else break; for (int x = curX + 1, y = curY - 1; 0 <= x && x < 10 && 0 <= y && y < 10; x++, y--) if (!board[x][y]) ways.push_back(curX * 10 + curY); else break; for (int x = curX - 1, y = curY + 1; 0 <= x && x < 10 && 0 <= y && y < 10; x--, y++) if (!board[x][y]) ways.push_back(curX * 10 + curY); else break; for (int x = curX - 1, y = curY - 1; 0 <= x && x < 10 && 0 <= y && y < 10; x--, y--) if (!board[x][y]) ways.push_back(curX * 10 + curY); else break; } else { if (curX - 1 >= 0 && curY - 1 >= 0 && !board[curX - 1][curY - 1]) ways.push_back(curX * 10 + curY); if (curX - 1 >= 0 && curY + 1 < 10 && !board[curX - 1][curY + 1]) ways.push_back(curX * 10 + curY); } } } if (!ways.size()) return false; return true; } int main(){ freopen("chess.in", "r", stdin); freopen("chess.out", "w", stdout); memset(board, 0, sizeof(board)); memset(isKing, 0, sizeof(isKing)); for (int i = 0; i < 10; i++) for (int j = 0; j < 10; j++) { char c; scanf(" %c", &c); board[i][j] = c - '0'; } for (int i = 0; i < 10; i++) for (int j = 0; j < 10; j++) { char c; scanf(" %c", &c); isKing[i][j] = c - '0'; } getAvailable(); if (!ways.size()) printf("0\n"); else { sort(ways.begin(), ways.end()); printf("%d\n", (int)ways.size()); for (int i = 0; i < (int)ways.size(); i++) printf("(%d,%d)\n", ways[i] / 10 + 1, ways[i] % 10 + 1); } }
思路:状压DP.
对后续决策有影响的是什么?
现在已经吃了哪些馅饼
令F[i][s]表示考虑前i次馅饼掉落事件,吃了s这个二进制状态表示的馅饼,期望的美味值
对于每一次掉馅饼,枚举掉下来的馅饼是谁
若s&a[j]==a[j](a[j]为前提馅饼集合) F[i][s] -> F[i+1][s|(1<<(j-1))] 注意要 /n
递推的顺序?
一个起始状态,多个目标状态,正推会导致无效状态
反着推
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int n,k,x,y; int w[20],f[20]; double dp[110][40010]; int main(){ freopen("bonus.in","r",stdin); freopen("bonus.out","w",stdout); scanf("%d%d",&n,&k); for(int i=0;i<n;i++){ scanf("%d",&w[i]); while(scanf("%d",&x)&&x) f[i]|=1<<x-1; } for(int s=0;s<(1<<n);s++) dp[k][s]=0; for(int i=k-1;i>=0;i--) for(int s=0;s<(1<<n);s++) for(int j=0;j<n;j++) if((s&f[j])==f[j]) dp[i][s]+=1.0/n*max(dp[i+1][s],dp[i+1][s|(1<<j)]+w[j]); else dp[i][s]+=1.0/n*dp[i+1][s]; printf("%.6f\n",dp[0][0]); }