ACM-ICPC 2018 北京赛区网络预赛(A B C D H)
自闭症患者
A. Saving Tang Monk II
题目链接
题面:
划掉
题意:
大搜索,队友写的
思路:
大搜索,队友写的
AC代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
char pic[102][102];
int dp[6][102][102];
struct step {
int x, y, w;
step() {}
step(int _x, int _y, int _w) : x(_x), y(_y), w(_w) {}
};
queue<step> bfs;
int dirx[4] = { -1, 0, 1, 0 };
int diry[4] = { 0, 1, 0, -1 };
int main() {
int x, y;
while (scanf("%d %d", &x, &y) != EOF && x > 0 && y > 0) {
for (int i = 0; i < x; i++) {
scanf("%s", pic[i]);
}
memset(dp, 0x3f3f3f3f, sizeof(dp));
while (!bfs.empty()) bfs.pop();
int sx, sy, tx, ty;
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
if (pic[i][j] == 'S') sx = i, sy = j;
if (pic[i][j] == 'T') tx = i, ty = j;
}
}
dp[0][sx][sy] = 0;
bfs.push(step(sx, sy, 0));
while (!bfs.empty()) {
step topx = bfs.front();
bfs.pop();
for (int k = 0; k < 4; k++) {
int nt = dp[topx.w][topx.x][topx.y];
int nx = topx.x + dirx[k];
int ny = topx.y + diry[k];
int nw = topx.w;
if (nx >= 0 && ny >= 0 && nx < x && ny < y) {
if (pic[nx][ny] == '#') {
if (nw == 0) continue;
nw--;
nt++;
} else if (pic[nx][ny] == 'B') {
if (nw < 5) nw++;
}
if (pic[topx.x][topx.y] != 'P') {
nt++;
}
if (nt < dp[nw][nx][ny]) {
dp[nw][nx][ny] = nt;
if (pic[nx][ny] != 'T') {
bfs.push(step(nx, ny, nw));
}
}
}
}
}
// for (int w = 0; w <= 5; w++) {
// for (int i = 0; i < x; i++) {
// for (int j = 0; j < y; j++) {
// printf("%d ", dp[w][i][j]);
// }printf("\n");
// }printf("\n\n");
// }
int ans = 0x3f3f3f3f;
for (int i = 0; i <= 5; i++) {
ans = min(ans, dp[i][tx][ty]);
}
printf("%d\n", ans == 0x3f3f3f3f ? -1 : ans);
}
return 0;
}
B. Tomb Raider
题目链接
题面:
划掉
题意:
寻址n个串的最长公共子序列。
思路:
拿一个最短串枚举所有子序列,在其他串中查找。暴力
AC代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <cmath>
#include <map>
using namespace std;
typedef long long LL;
const int MAXN = 1000005;
string s[12];
int use[10];
string ans;
int main()
{
int n;
string temp;
string now;
while(cin >> n){
for(int i = 0; i < n; ++i){
cin >> s[i];
}
for(int i = 1; i < n; ++i){
s[i] += s[i];
//cout << s[i] << endl;
}
int len = s[0].length();
int maxx = (1<<len);
ans = "";
for(int i = 0; i < maxx; ++i){
temp = "";
int cnt = 0;
for(int j = 0; j < len; ++j){
if(i&(1<<j)){
temp += s[0][j];
}
}
int tl = temp.length();
for(int x = 0; x < tl; ++x){
now = temp.substr(x+1, tl-(x+1)) + temp.substr(0, x);
now.push_back(temp[x]);
int nl = now.length();
//cout << now << endl;
bool flag = true;
bool tempflag;
for(int j = 1; j < n; ++j){
int lj = s[j].length()/2;
tempflag = false;
for(int st = 0; st < lj; ++st){
if(s[j][st] != now[0]) continue;
int cur = 1;
if(nl == 1){
tempflag = true;
break;
}
for(int k = st+1; k < st+lj; ++k){
if(s[j][k] == now[cur]){
++cur;
if(cur == nl){
tempflag = true;
break;
}
}
}
if(tempflag) break;
}
if(!tempflag){
flag = false;
break;
}
}
if(flag){
//cout << now << endl;
if(now.length() > ans.length()){
ans = now;
reverse(now.begin(), now.end());
if(now < ans){
ans = now;
}
}else if(now.length() == ans.length()){
if(now < ans){
ans = now;
}
reverse(now.begin(), now.end());
if(now < ans){
ans = now;
}
}
}
}
}
if(ans == ""){
cout << 0 << endl;
}else{
cout << ans << endl;
}
}
}
C. Cheat
题目链接
题面:
划掉
题意:
斗地主。
思路:
大模拟,队友写的。
AC代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
int dictOrder[] = {9, 1, 2, 3, 4, 5, 6, 7, 8, 0, 10, 12, 11};
int cards[4][13];
int fuck[4][13];
int tables[13];
char fv[5];
int rankNow = 0, rounderRank = -1, rounderCnt = -1, roundext = -1, roundNow = 0;
int getcard(char* sp) {
#define card(a, b) if (strcmp(sp, a) == 0) return b;
card("A", 0); card("2", 1); card("3", 2); card("4", 3); card("5", 4); card("6", 5);
card("7", 6); card("8", 7); card("9", 8); card("10", 9); card("J", 10); card("Q", 11);
card("K", 12);
return -1;
#undef card
}
const char* getcardII(int sp) {
#define card(b, a) if (sp == a) return b;
card("A", 0); card("2", 1); card("3", 2); card("4", 3); card("5", 4); card("6", 5);
card("7", 6); card("8", 7); card("9", 8); card("10", 9); card("J", 10); card("Q", 11);
card("K", 12);
return "?";
#undef card
}
int findSmallest(int p) {
for (int i = 0; i < 13; i++) {
if (cards[p][dictOrder[i]] > 0) {
return dictOrder[i];
}
}
return -1;
}
int findNextCard(int p) {
for (int i = 0; i < 13; i++) {
if (fuck[p][i] > 0) {
fuck[p][i]--;
return i;
}
}
return -1;
}
void putOneDictSmallest(int p) {
int ck = findSmallest(p);
if (ck >= 0) {
cards[p][ck]--;
rounderCnt = 1;
rounderRank = ck;
tables[ck]++;
}
}
void putSomeTrueCard(int p, int cnt) {
rounderCnt = cnt;
cards[p][rankNow] -= cnt;
rounderRank = rankNow;
tables[rankNow] += cnt;
}
bool action(int p, bool realDo, int rankx) {
if (realDo) roundext = -1;
if (p == 0) {
if (cards[p][rankx] > 0) {
if (realDo) putSomeTrueCard(p, 1);
return true;
} else {
if (realDo) putOneDictSmallest(p);
return false;
}
} else if (p == 1) {
if (cards[p][rankx] > 0) {
if (realDo) putSomeTrueCard(p, cards[p][rankx]);
return true;
} else {
if (realDo) putOneDictSmallest(p);
return false;
}
} else if (p == 2) {
if (cards[p][rankx] > 0) {
if (realDo) putSomeTrueCard(p, cards[p][rankx]);
return true;
} else {
if (realDo) {
int nums = 9999, idx = -1;
for (int i = 0; i < 13; i++) {
if (cards[p][dictOrder[i]] > 0) {
if (cards[p][dictOrder[i]] < nums) {
nums = cards[p][dictOrder[i]];
idx = dictOrder[i];
}
}
}
rounderCnt = cards[p][idx];
cards[p][idx] = 0;
rounderRank = idx;
tables[idx] += rounderCnt;
}
return false;
}
} else if (p == 3) {
if (cards[p][rankx] > 2) {
if (realDo) putSomeTrueCard(p, cards[p][rankx]);
return true;
} else {
if (realDo) {
putSomeTrueCard(p, cards[p][rankx]);
roundext = findSmallest(p);
if (roundext >= 0) {
cards[p][roundext]--;
tables[roundext]++;
}
return roundext == -1;
}
return false;
}
}
}
bool shouldFuck(int p) {
if (p == 0) {
if ((roundNow + 1) % 4 == p && !action(p, false, (rankNow + 1) % 13)) {
return true;
} else {
return cards[p][rankNow] + (rounderCnt + (roundext >= 0)) > 4;
}
} else if (p == 1) {
return (roundNow + 1) % 4 == p && !action(p, false, (rankNow + 1) % 13);
} else if (p == 2) {
return cards[p][rankNow] == 4;
} else if (p == 3) {
return findSmallest(roundNow % 4) == -1;
}
}
void getAllCards(int p) {
for (int i = 0; i < 13; i++) {
cards[p][i] += tables[i];
tables[i] = 0;
}
}
void printCards() {
memcpy(fuck, cards, sizeof(cards));
for (int i = 0; i < 4; i++) {
for (int k = 0; k < 998; k++) {
int next = findNextCard(i);
if (next == -1) {
if (k == 0) printf("WINNER");
printf("\n");
break;
}
else {
if (k > 0) printf(" ");
printf("%s", getcardII(next));
}
}
}
}
int main() {
bool gaming = true;
while (gaming) {
memset(cards, 0, sizeof(cards));
memset(tables, 0, sizeof(tables));
for (int i = 0, j = -1; i < 52; i++) {
if (i % 13 == 0) j++;
if (scanf("%s", fv) == EOF) {
gaming = false;
break;
}
int cc = getcard(fv);
if (cc >= 0) cards[j][cc]++;
}
rankNow = 0, roundNow = 0, rounderRank = -1, rounderCnt = -1, roundext = -1;
if (gaming) {
while (true) {
//printf("round: %s\n", getcardII(rankNow));
bool really = action(roundNow % 4, true, rankNow);
//printCards();
//printf("rankcnt %d ext: %s\n", rounderCnt, getcardII(roundext));
//printf("p%d is really: %d\n", roundNow % 4, really);
for (int j = roundNow + 1; j < roundNow + 4; j++) {
if (shouldFuck(j % 4)) {
//printf("p%d do fuck!\n", j % 4);
if (!really) {
getAllCards(roundNow % 4);
} else {
getAllCards(j % 4);
}
break;
}
}
rankNow = (rankNow + 1) % 13;
if (findSmallest(roundNow % 4) == -1) break;
roundNow++;
}
printCards();
}
}
return 0;
}
D. 80Days
题目链接
题面:
划掉
题意:
n个成环的城市,到达第i个城市获得 a i a_i ai,离开丢掉 b i b_i bi,初始有c,全程拥有值不能为负数,问是否可行,可行就输出最小的出发点。
思路:
尺取法,维护一个连续段的区间以及C+在该区间旅游费用和,左端点不变,右端点向右移,如果遇到无法进行的情况则移动左端点。
AC代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <cmath>
#include <map>
using namespace std;
typedef long long LL;
const int MAXN = 1000005;
LL a[2*MAXN];
LL b[2*MAXN];
int main()
{
int t;
cin >> t;
int n;
LL c;
while(t--){
scanf("%d%lld", &n, &c);
for(int i = 1; i <= n; ++i){
scanf("%lld", &a[i]);
a[n+i] = a[i];
}
for(int i = 1; i <= n; ++i){
scanf("%lld", &b[i]);
b[n+i] = b[i];
}
int l = 1, r = 1;
LL now = c + a[1];
bool flag = false;
while(true){
now -= b[r];
while(now < 0 && l < r){
now -= a[l];
now += b[l];
l++;
}
if(l == r && now < 0){
l++;
r++;
now = c + a[l];
continue;
}
r++;
if(r-l == n){
flag = true;
break;
}
now += a[r];
while(now < 0 && l < r){
now -= a[l];
now += b[l];
l++;
}
if(l > n){
flag = false;
break;
}
}
if(flag){
printf("%d\n", l);
}else{
printf("-1\n");
}
}
}
H. K-Demensional Foil II
题目链接
题面:
划掉
题意:
K维空间,给定一个曼哈顿距离意义下的球,N个点,求这些点到该球上在欧几里得距离下最小的点。
思路:
直接考虑对欧几里得距离进行缩小,那么可以写成一个类似于方差形式的表达式,那么要使得该表达式最小,令这K维当中对表达式值贡献最大的值减小。
问题变形为满足哈密顿距离小于R时放缩该表达式使得其值最小,二分即可。
AC代码:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <stack>
#include <bitset>
using namespace std;
#define FSIO ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define DEBUG(a) cout<<"DEBUG: "<<(a)<<endl;
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define REP(i,st,ed) for(int i=st;i<=ed;++i)
#define IREP(i,st,ed) for(int i=ed;i>=st;--i)
#define TCASE(T) cin>>T;while(T--)
const int MAXN = 105;
const int MOD = 2333333 ;
const int INF = 1e9+7;
int _;
using namespace std;
const double EPS = 1e-6;
double foil[MAXN];
double spcf[MAXN];
double go[MAXN];
bool mk[MAXN];
int N, K;
double R;
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w+",stdin);
TCASE(_)
{
scanf("%d%d",&N,&K);
scanf("%lf",&R);
REP(i,1,K) scanf("%lf",&foil[i]);
REP(t,1,N)
{
REP(i,1,K)
{
scanf("%lf",&spcf[i]);
go[i] = fabs(spcf[i]-foil[i]);
mk[i] = (spcf[i]>=foil[i]);
}
double minn = 0;
double maxn = 1e8;
double mid, tmp;
while(minn+EPS<=maxn)
{
mid = (minn+maxn)/2.0;
tmp = 0;
REP(kk,1,K) tmp+=max(0.0,go[kk]-mid);
if(tmp<=R) maxn = mid-EPS;
else minn = mid+EPS;
}
REP(i,1,K)
{
if(go[i]>=maxn) go[i]=maxn;
if(mk[i]) tmp = spcf[i]-go[i];
else tmp = spcf[i]+go[i];
printf("%.5f ",tmp);
}
printf("\n");
}
}
return 0;
}