Codeforces Round #390 (Div. 2)(A,B,C(記憶化搜尋),D(貪心,優先佇列))
阿新 • • 發佈:2018-12-24
/* Codeforces Round #390 (Div. 2) 時間: 2017/02/16 A. Lesha and array splitting 題意:將集合分成幾個小集合,要求小集合的和不為0. 題解:遍歷過去,一直到不滿足集合並數字非0前生成一個集合 */ #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> #include <queue> using namespace std; const int INF = 0x3f3f3f3f; const int N = 110; int a[N]; int rel[N],rer[N]; int main() { int n; while(~scanf("%d",&n)) { int flag = 0; for(int i = 1; i <= n; i++) { scanf("%d",&a[i]); if(a[i]) flag = 1; } if(!flag) puts("NO"); else { puts("YES"); int r = 1,l = 1; int sum = 0; int k = 0; while(r <= n) { sum += a[r]; if(!sum && a[r]) { rel[k] = l; rer[k++] = r-1; l = r; } else r++; } rel[k] = l; rer[k++] = r-1; printf("%d\n",k); for(int i = 0; i < k; i++) printf("%d %d\n",rel[i],rer[i]); } } return 0; }
/* Codeforces Round #390 (Div. 2) 時間: 2017/02/16 B. Ilya and tic-tac-toe game 題意:給你一個4*4的棋盤,誰先連成三子誰贏,‘x’為先手下的棋,‘o’為後手下的棋,‘.’為空,問先手下一步能不贏 題解:將列舉每個空格位置,判斷位置可行性 */ #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> #include <queue> using namespace std; const int INF = 0x3f3f3f3f; const int N = 10; int p[N][N]; bool hefa(int x,int y) { if(x >= 0 && x <= 3 && y >= 0 && y <= 3) return true; return false; } bool pan(int x,int y) { if(hefa(x-1,y) && hefa(x-2,y) && p[x-1][y] == 1 && p[x-2][y] == 1) return true; if(hefa(x-1,y-1) && hefa(x-2,y-2) && p[x-1][y-1] == 1 && p[x-2][y-2] == 1) return true; if(hefa(x+1,y) && hefa(x+2,y) && p[x+1][y] == 1 && p[x+2][y] == 1) return true; if(hefa(x+1,y+1) && hefa(x+2,y+2) && p[x+1][y+1] == 1 && p[x+2][y+2] == 1) return true; if(hefa(x-1,y-1) && hefa(x+1,y+1) && p[x-1][y-1] == 1 && p[x+1][y+1] == 1) return true; if(hefa(x-1,y) && hefa(x+1,y) && p[x-1][y] == 1 && p[x+1][y] == 1) return true; if(hefa(x,y-1) && hefa(x,y-2) && p[x][y-1] == 1 && p[x][y-2] == 1) return true; if(hefa(x-1,y+1) && hefa(x-2,y+2) && p[x-1][y+1] == 1 && p[x-2][y+2] == 1) return true; if(hefa(x,y+1) && hefa(x,y+2) && p[x][y+1] == 1 && p[x][y+2] == 1) return true; if(hefa(x+1,y-1) && hefa(x+2,y-2) && p[x+1][y-1] == 1 && p[x+2][y-2] == 1) return true; if(hefa(x+1,y-1) && hefa(x-1,y+1) && p[x+1][y-1] == 1 && p[x-1][y+1] == 1) return true; if(hefa(x,y-1) && hefa(x,y+1) && p[x][y-1] == 1 && p[x][y+1] == 1) return true; return false; } int main() { char s[N]; while(~scanf("%s",s)) { int a; for(int j = 0; j < 4; j++) { if(s[j] == 'x') a = 1; else if(s[j] == '.') a = 0; else a = 2; p[0][j] = a; } for(int i = 1; i < 4; i++) { scanf("%s",s); for(int j = 0; j < 4; j++) { if(s[j] == 'x') a = 1; else if(s[j] == '.') a = 0; else a = 2; p[i][j] = a; } } int flag = 0; for(int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++) { //printf("%d ",p[i][j]); if(!p[i][j] && pan(i,j)) { flag = 1; break; } } //puts(""); if(flag) break; } if(flag) puts("YES"); else puts("NO"); } return 0; }
/* Codeforces Round #390 (Div. 2) 時間: 2017/02/17 C題 Vladik and chat 題意:給你幾段對話,和幾個說話人的名字,要求得到不可知說話人的名字。 秉承的原則: 1.一個人不可能說兩個連續的話 2.說話的人不能提到自己的名字 題解: dp[i][j] = 1 代表第i句可能是j人說。 dp2[i][j] = 1 代表考慮前i-1句,第i-1句是j人說。 */ #include <cstdio> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #include <queue> #include <stack> #include <map> using namespace std; #define LL long long const int INF = 0x3f3f3f3f; const int N = 150; map<string,int> mp; int dp[N][N]; int dp2[N][N]; int res[N]; int flag; int n,m; int cal(int id, int limit) { int &ret = dp2[id][limit]; if (id > m) return ret = 1; if (ret != -1) return ret; ret = 0; for (int i = 1; i <= n; i++) { if(dp[id][i] && limit != i) { ret = max(ret, cal(id + 1, i)); } } return ret; } int main() { int T; scanf("%d",&T); while(T--) { mp.clear(); memset(dp,0,sizeof(dp)); memset(dp2,-1,sizeof(dp2)); scanf("%d",&n); getchar(); string name[N]; for(int i = 0; i < n; i++) { cin >> name[i+1]; mp[name[i+1]] = i+1; } scanf("%d",&m); getchar(); char s[N]; string rec[N]; flag = 1; for(int i = 1; i <= m; i++) { gets(s); int len = strlen(s); int j; string a; for(j = 0; j < len; j++) { if(s[j] == ':') break; a += s[j]; } int begin = j; for(int j = begin; j < len; j++) rec[i] += s[j]; if(a == "?") { for(int k = 1; k <= n; k++) dp[i][k] = 1; for(j = begin; j < len; j++) { if(!isalnum(s[j])) continue; string b; int k; for(k = j; k < len; k++) { if(!isalnum(s[k])) break; b += s[k]; } j = k; if(mp[b]) dp[i][mp[b]] = 0; } } else { int id = mp[a]; dp[i][id] = 1; for(j = begin; j < len; j++) { if(!isalnum(s[j])) continue; string b; int k; for(k = j; k < len; k++) { if(!isalnum(s[k])) break; b += s[k]; } j = k; if(b == a) { flag = 0; break; } } } } if(!flag) puts("Impossible"); else { int ans = cal(1,0); if(!ans) puts("Impossible"); else { int k; for (int i = 1; i <= n; i++) { if (dp2[m + 1][i] == 1) { k = i; break; } } int id = m; while (1) { res[id] = k; if (id == 1) break; for (int i = 1; i <= n; i++) { if (k != i&&dp2[id][i] == 1) { k = i; break; } } id--; } for (int i = 1; i <= m; i++) cout << name[res[i]] << rec[i] << endl; } } } return 0; }
/*
Codeforces Round #390 (Div. 2)
時間: 2017/02/16
D. Fedor and coupons
題意:給你n個具有範圍的禮券,選擇k個禮券,要求k個禮券交叉包含的範圍最大,輸出範圍大小和選擇的禮券。
題解:要選k個禮券維護最大,我們要使禮券交叉左極限小,右極限大。這樣看來將禮券按左極限排序,然後右極限用優先佇列維護即可。
*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 300010;
struct asd
{
int l,r,id;
friend bool operator< (asd n1,asd n2)
{
return n1.r > n2.r;
}
}a[N];
bool cmp(asd n1,asd n2)
{
return n1.l < n2.l;
}
int main()
{
int n,k;
while(~scanf("%d%d",&n,&k))
{
for(int i = 1; i <= n; i++)
{
scanf("%d%d",&a[i].l,&a[i].r);
a[i].id = i;
}
sort(a+1,a+n+1,cmp);
priority_queue<asd> q;
int ans = 0,res = 0;
for(int i = 1; i <= n; i++)
{
asd temp;
if(!q.empty())
temp = q.top();
if(q.size() < k)
q.push(a[i]);
else if(temp.r < a[i].r)
{
q.pop();
q.push(a[i]);
}
if(q.size() == k)
{
temp = q.top();
if(temp.r-a[i].l+1 > ans)
{
ans = temp.r-a[i].l+1;
res = i;
}
}
}
printf("%d\n",ans);
if(ans)
{
int id = 0;
for(int i = 1; i <= res && id < k; i++)
{
if(a[res].l+ans-1 <= a[i].r)
{
printf("%d ",a[i].id);
id++;
}
}
}
else
{
for(int i = 1; i <= k; i++)
printf("%d ",i);
}
puts("");
}
return 0;
}