徐州網絡賽2018
阿新 • • 發佈:2018-10-18
實用 scan dfs ++ int 價值 con != 無效
徐州網絡賽2018
網絡賽的題比賽應該不會出了吧 嗯......
【記憶化搜索求PN態】 BE, GE or NE
- 題意:三個操作,增加,減少,加負號。一個人要讓該數字>=r,一個人要讓該數字小於等於l。
- 很明顯對於先手來說肯定是讓分數最高最優,對於後手來說肯定是讓分數最低最優。我們考慮所有的方案,肯定是 3^n,所以我們可以記憶化搜索, 一共只有 1000*200 種狀態, 所以一定是可以算出來的
一個點為必勝態,當且僅當他的後繼 有一個必敗態
一個點為必敗態,當且僅當他所有的後繼 都是必勝態
考慮這道題, 如果第一個人可以贏,他不會選擇平, 更不會選擇輸
對於第二個人同理
#include <bits/stdc++.h> using namespace std; #define ll long long const int maxn=1005; int down,up,s,n; int a[maxn],b[maxn],c[maxn]; int dp[maxn][305]; int high,low; map<int,int>mp; int dfs(int pos,int now){ if(pos==n+1){ if(now>=high){ return 2; } else if(now>low) return 1; else return 0; } if(dp[pos][mp[now]]!=-1) return dp[pos][mp[now]]; if(pos%2==1){ int op=0; if(a[pos]){ op=max(op,dfs(pos+1,min(now+a[pos],up))); } if(b[pos]){ op=max(op,dfs(pos+1,max(now+b[pos],down))); } if(c[pos]){ op=max(op,dfs(pos+1,-now)); } return dp[pos][mp[now]]=op; } else{ int op=1e9; if(a[pos]){ op=min(op,dfs(pos+1,min(now+a[pos],up))); } if(b[pos]){ op=min(op,dfs(pos+1,max(now+b[pos],down))); } if(c[pos]){ op=min(op,dfs(pos+1,-now)); } return dp[pos][mp[now]]=op; } } int main() { int tol=0;mp.clear(); for (int i = -100; i <=100 ; ++i) { mp[i]=++tol; } down=-100,up=100; memset(dp,-1,sizeof(dp)); scanf("%d%d%d%d",&n,&s,&high,&low); for (int j = 1; j <=n; ++j) { scanf("%d%d%d",&a[j],&b[j],&c[j]); b[j]=-b[j]; } int op=dfs(1,s); if(op==2){ puts("Good Ending"); } else if(op==1){ puts("Normal Ending"); } else puts("Bad Ending"); return 0; }
記憶化搜索:算法上依然是搜索的流程,但是搜索到的一些解用動態規劃的那種思想和模式作一些保存。
一般說來,動態規劃總要遍歷所有的狀態,而搜索可以排除一些無效狀態。
更重要的是搜索還可以剪枝,可能剪去大量不必要的狀態,因此在空間開銷上往往比動態規劃要低很多。
記憶化算法在求解的時候還是按著自頂向下的順序,但是每求解一個狀態,就將它的解保存下來,
以後再次遇到這個狀態的時候,就不必重新求解了。
這種方法綜合了搜索和動態規劃兩方面的優點,因而還是很有實用價值的
【暴力求期望+題意】Cacti Lottery
這題真的題意殺.....
挺難讀懂的,123代表已經知道的數,*代表知道是那些數但是不知道具體的,#代表未知的數。然後求期望。
#include <bits/stdc++.h> using namespace std; typedef long long ll; int num[25] = { 0,0,0,0,0,0,10000,36,720,360,80,252,108,72,54,180,72,180,119,36,360,1080,144,1800,3600}; char mp[5][5]; int vis[10]; int cnt = 0, cnt1 = 0, cnt2 = 0; char mp2[10]; int fial[10]; int idx = 0; double allans = 0; int ans[10]; int A(int n, int m) { int res = 1; for (int i = 1; i <= m; i++) { res *= (n - i + 1); } return res; } void check1() { ans[0] += num[fial[0] + fial[1] + fial[2]]; ans[1] += num[fial[3] + fial[4] + fial[5]]; ans[2] += num[fial[6] + fial[7] + fial[8]]; ans[3] += num[fial[0] + fial[3] + fial[6]]; ans[4] += num[fial[1] + fial[4] + fial[7]]; ans[5] += num[fial[2] + fial[5] + fial[8]]; ans[6] += num[fial[0] + fial[4] + fial[8]]; ans[7] += num[fial[2] + fial[4] + fial[6]]; } void dfs2(int num) { if (num == 9) { check1(); return; } if (fial[num] != 0) dfs2(num + 1); else { for (int i = 1; i <= 9; i++) { if (vis[i])continue; vis[i] = 1; fial[num] = i; dfs2(num + 1); fial[num] = 0; vis[i] = 0; } } } void dfs(int num) { if (num == 9) { memset(ans, 0, sizeof(ans)); dfs2(0); int maxx = 0; for (int i = 0; i < 8; i++) { maxx = max(maxx, ans[i]); } allans += maxx / (A(cnt2,cnt2)*1.0); return; } if (mp2[num] == '#') { dfs(num + 1); } else if (mp2[num] != '*') { fial[num] = mp2[num] - '0'; dfs(num + 1); } else { for (int i = 1; i <= 9; i++) { if (vis[i]) continue; vis[i] = 1; fial[num] = i; dfs(num + 1); vis[i] = 0; } } } int main() { int T; scanf("%d", &T); while (T--) { memset(vis, 0, sizeof(vis)); memset(fial, 0, sizeof(fial)); memset(mp2, 0, sizeof(mp2)); int p = 0; cnt1 = 0; cnt2 = cnt = 0; idx = 0; allans = 0; for (int i = 1; i <= 3; i++) { scanf("%s", mp[i]); int len = strlen(mp[i]); for (int j = 0; j<len; j++) { if (mp[i][j] <= '9'&&mp[i][j] >= '0') { int k = mp[i][j] - '0'; vis[k] = 1; cnt1++; } if (mp[i][j] == '*') cnt++; mp2[idx++] = mp[i][j]; } } cnt2 = 9 - cnt1 - cnt; dfs(0); int k = A(9 - cnt1, cnt); double tt = allans / k * 1.0; printf("%.6lf\n", tt); } return 0; }
【set+模擬】 Trace
當初沒做出來,用set維護就可以解決問題。
也可以說是思維題吧
#include <bits/stdc++.h>
using namespace std;
#define ll long long
vector<int>vector1;
vector<int>vector2;
ll solve(vector<int>v1){
ll res=0;
set<int>set1;
int len=v1.size();
for (int i = len-1; i >=0 ; --i) {
set<int>::iterator it=set1.lower_bound(v1[i]);
if(it==set1.begin()){
res+=v1[i];
}
else{
it--;
res+=v1[i]-*it;
}
set1.insert(v1[i]);
}
return res;
}
int main(){
int n,x,y;
scanf("%d",&n);
for (int i = 1; i <=n; ++i) {
scanf("%d%d",&x,&y);
vector1.push_back(x);
vector2.push_back(y);
}
printf("%lld\n",solve(vector1)+solve(vector2));
}
徐州網絡賽2018