1. 程式人生 > >2018.8.22 練習賽

2018.8.22 練習賽

stdio.h 一行 fine content urn 整數 i++ class status

  • T1 井字棋
  • 題意:給定一井字棋殘局,問結果
  • 狀壓記憶化暴搜,博弈
  • 技術分享圖片
      1 #include<stdio.h>
      2 #include<cstdlib>
      3 #include<algorithm>
      4 #include<cstring>
      5 using namespace std;
      6 int po[20],ch[256];
      7 int f[100000][3];
      8 int judge(int s)
      9 {
     10     int g[10];
     11     for(int i=1,ss=s;i<=9
    ;i++,ss/=3) g[i]=ss%3; 12 if(g[1]==g[2]&&g[2]==g[3]) 13 { 14 if(g[1]==1) return 1; 15 if(g[1]==2) return -1; 16 } 17 if(g[4]==g[5]&&g[5]==g[6]) 18 { 19 if(g[4]==1) return 1; 20 if(g[4]==2) return -1; 21 } 22 if
    (g[7]==g[8]&&g[8]==g[9]) 23 { 24 if(g[7]==1) return 1; 25 if(g[7]==2) return -1; 26 } 27 if(g[1]==g[4]&&g[4]==g[7]) 28 { 29 if(g[1]==1) return 1; 30 if(g[1]==2) return -1; 31 } 32 if(g[2]==g[5]&&g[5]==g[8
    ]) 33 { 34 if(g[2]==1) return 1; 35 if(g[2]==2) return -1; 36 } 37 if(g[3]==g[6]&&g[6]==g[9]) 38 { 39 if(g[3]==1) return 1; 40 if(g[3]==2) return -1; 41 } 42 if(g[1]==g[5]&&g[5]==g[9]) 43 { 44 if(g[1]==1) return 1; 45 if(g[1]==2) return -1; 46 } 47 if(g[3]==g[5]&&g[5]==g[7]) 48 { 49 if(g[3]==1) return 1; 50 if(g[3]==2) return -1; 51 } 52 return 0; 53 } 54 int cnt(int s){int ret=0;for(int i=1;i<=9;i++,s/=3) ret+=(s%3==0); return ret;} 55 int dfs(int s,int who) 56 { 57 if(judge(s)!=0) return judge(s); 58 else if(cnt(s)==0) return judge(s); 59 if(~f[s][who]) return f[s][who]; 60 int mmin=1,mmax=-1; 61 if(who==1) 62 { 63 for(int i=1,ss=s;i<=9;i++,ss/=3) 64 { 65 int t=ss%3; 66 if(t==0) mmax=max(mmax,dfs(s+po[i-1],2)); 67 } 68 return f[s][who]=mmax; 69 } 70 else 71 { 72 for(int i=1,ss=s;i<=9;i++,ss/=3) 73 { 74 int t=ss%3; 75 if(t==0) mmin=min(mmin,dfs(s+po[i-1]*2,1)); 76 } 77 return f[s][who]=mmin; 78 } 79 } 80 int main() 81 { 82 memset(f,-1,sizeof(f)); 83 po[0]=1,ch[X]=2,ch[O]=1,ch[_]=0; 84 for(int i=1;i<=10;i++) po[i]=po[i-1]*3; 85 int T; 86 scanf("%d",&T); 87 while(T--) 88 { 89 int st=0,fc=0,sc=0; 90 char buf[5]; 91 for(int i=1;i<=3;i++) 92 { 93 scanf("%s",buf); 94 for(int j=0;j<3;j++) 95 { 96 st+=ch[buf[j]]*po[(i-1)*3+j]; 97 if(buf[j]==O) fc++; 98 else if(buf[j]==X)sc++; 99 } 100 } 101 int win=0; 102 if(fc==sc) win=dfs(st,1); 103 else win=dfs(st,2); 104 printf("%s\n",win==0?"E":win==1?"O":"X"); 105 }
    View Code

  • T2 ?asuchy
  • 題面:
  • (BZOJ)3749: [POI2015]?asuchy

    Time Limit: 10 Sec Memory Limit: 64 MBSec Special Judge
    Submit: 420 Solved: 164
    [Submit][Status][Discuss]

    Description

    圓桌上擺放著n份食物,圍成一圈,第i份食物所含熱量為c[i]。 相鄰兩份食物之間坐著一個人,共有n個人。每個人有兩種選擇,吃自己左邊或者右邊的食物。如果兩個人選擇了同一份食物,這兩個人會平分這份食物,每人獲得一半的熱量。 假如某個人改變自己的選擇後(其他n-1個人的選擇不變),可以使自己獲得比原先更多的熱量,那麽這個人會不滿意。 請你給每個人指定應該吃哪一份食物,使得所有人都能夠滿意。

    Input

    第一行一個整數n(2<=n<=1000000),表示食物的數量(即人數)。食物和人都從1~n編號。 第二行包含n個整數c[1],c[2],…,c[n](1<=c[i]<=10^9)。 假設第i個人(1<=i<n)左邊是第i份食物,右邊是第i+1份食物;而第n個人左邊是第n份食物,右邊是第1份食物。

    Output

    如果不存在這樣的方案,僅輸出一行NIE。 如果存在這樣的方案,輸出一行共n個整數,第i個整數表示第i個人選擇的食物的編號。如果有多組這樣的方案,輸出任意一個即可。

    Sample Input

    5
    5 3 7 2 9

    Sample Output

    2 3 3 5 1
  • 狀態惡心的dp,狀態:f[i][j]表示第i個食物處於第j種狀態:被左邊吃,被右邊吃,被兩邊吃,兩邊都不吃,轉移見code(ps:不存在無解的情況!)話說似乎貪心+隨機化之類可以騙到大部分分……多跑幾遍說不定就A了……
  • 技術分享圖片
     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 #define ll long long
     5 using namespace std;
     6  
     7 ll n;
     8 ll a[1000005];
     9 ll f[1000005][5];
    10 ll ans[1000005];
    11 // 1 left
    12 // 2 right
    13 // 3 yiqi
    14 // 4 doubu
    15  
    16 bool dp(ll v) {
    17     memset(f,0,sizeof(f));
    18     f[1][v]=1;
    19     for(int i=2; i<=n; i++) {
    20         if(f[i-1][1]&&a[i-1]<=2*a[i]) f[i][1]=1;
    21         if(f[i-1][1]&&a[i-1]<=a[i]) f[i][3]=1;
    22         if(f[i-1][2]&&a[i-1]*2>=a[i]) f[i][2]=2;
    23         if(f[i-1][2]&&a[i-1]>=a[i]) f[i][4]=2;
    24         if(f[i-1][3]&&a[i-1]>=a[i]*2) f[i][4]=3;
    25         if(f[i-1][3]&&a[i-1]>=a[i]) f[i][2]=3;
    26         if(f[i-1][4]&&a[i-1]<=a[i]) f[i][1]=4;
    27         if(f[i-1][4]&&a[i-1]*2<=a[i]) f[i][3]=4;
    28     }
    29     if(!f[n][v]) return 0;
    30     for(int i=n; i>=1; i--) {
    31         if(v==1) ans[i-1]=(i-1)%(n-1)+1;
    32         if(v==2) ans[i]=(i-1)%(n-1)+1;
    33         if(v==3) ans[i-1]=ans[i]=(i-1)%(n-1)+1;
    34         v=f[i][v];
    35     }
    36     for(int i=1; i<n; i++) printf("%lld ",ans[i]);
    37     return 1;
    38 }
    39  
    40 int main() {
    41     scanf("%lld",&n);
    42     for(int i=1; i<=n; i++) scanf("%lld",&a[i]);
    43     a[++n]=a[1];
    44     for(int i=1;i<=4;i++) if(dp(i)) return 0;
    45 }
    View Code

  • T3 泰拉瑞亞
  • 題意:完成兩個操作:單點增加某點的值,快速查找某點左右兩邊第一個比它值大的點。
  • 這道真是毒瘤題……大概思路……分塊維護塊中單調棧,每個塊再用線段樹維護單點修改……代碼暫無……

2018.8.22 練習賽