一道區間dp和一道字符串

 

牛X網測試rating系統,葉神開的bnu的重現賽,送8個T恤,就作了兩個題參與下抽獎,打了三場了,不出意料的都沒抽中我 =-=ios

 第一道:c++

小Q同窗爲了準備今年的ICPC Regional,計劃在m天以內刷掉n道題,每道題有一個難度值,其中第i道題的難度值爲a[i]app

然而處於半頹廢狀態中的小Q同窗不但願在同一天中作難度差距懸殊的題目,定義第i天中刷的題的難度的最大值減最小值爲d[i](若是第i天沒有刷題,則d[i]=0),那麼整個計劃的難度爲\sum_{i=1}^{m}{d^2[i]}函數

小Q同窗能夠按照任意的順序刷題,而且一天中能夠刷任意多道題,可是每道題只須要作一次,如今小Q同窗想知道完成這個計劃的總難度的最小值是多少。測試

 

Input

第一行是一個正整數T(\leq 10),表示測試數據的組數,優化

對於每組測試數據,google

第一行是兩個整數n(1\leq n \leq 500)m(1\leq m \leq 500),表示題數和天數,spa

第二行是n個整數a[i](0\leq a[i]\leq 1000000),表示每道題的難度值。設計

 

Output

對於每組測試數據,輸出一個整數,表示整個計劃的最小難度。3d

 

Sample Input

2
3 3
1 2 3
3 2
1 2 3

Sample Output

0
1

Hint

對於第一組樣例,最優方案是一天刷一題。

對於第二組樣例,一個最優方案是第一天刷難度值爲1和2的題,次日刷難度值爲3的題。

 

區間dp了,天數就是區間個數,天天的難度就是一個區間的最大最小差的平方,

求差值平方最小,因此難度相近的一塊兒作,排好序,只要找到已排序的全部題如何分割爲m份便可。

這裏時限5s很寬,直接三重暴力便可:

dp[i][j]表示前i天作j題的最小難度

新加入第j道題的時候,再加一重循環,遍歷前狀態中每道題,組成新的區間

dp[i][j] = min(dp[i][j],dp[i-1][k-1]+abs(a[j]-a[k])*abs(a[j]-a[k])); j和k爲新的區間

參考數據 2 4 6 8  2天完成 能夠 2 4一天 6 8 一天 結果8

            也能夠 2 4 6 一天 8一天 結果16 

顯然 新加入的8找6組成區間值更小一些,再加上 dp[1][2]也就是1天作 2 4道題的狀態 是最優值

 

固然能夠用斜率DP優化到二維,

能夠說是斜率優化dp的水題,找個好的模板把那幾個函數改下也能夠

注意初始化那裏通常int的已經不行了,普通的4個3f要改爲long long的8個3f,還有就是30行必須提早初始化,在轉移方程裏比較dp[i-1][j]會出現無限大比較無限大的錯誤

 1 #include <bits/stdc++.h>
 2 typedef long long ll;
 3 
 4 const ll INF = 0x3f3f3f3f3f3f3f3f;//這裏必需要設置超過int的,否則WA,後臺數據硬
 5 const int N = 500+10; 6 using namespace std; 7 int n,m,sum,res,flag; 8 long long a[N],dp[N][N]; 9 void init() 10 { 11 for(int i=1;i<=n;i++) 12 dp[0][i]=INF;//這種狀況是無限大的 13 dp[0][0] = 0; 14 } 15 int main() 16 { 17 // freopen("in.txt","r",stdin); 18 int i,j,k,cas,T,t,x,y,z; 19 scanf("%d",&T); 20 cas=0; 21 while(T--) 22  { 23 scanf("%d%d",&n,&m); 24  init(); 25 for(i=1;i<=n;i++)scanf("%lld",&a[i]); 26 sort(a+1,a+1+n); 27 for(i=1;i<=m;i++) 28 for(j=1;j<=n;j++) 29  { 30 dp[i][j] = dp[i-1][j]; 31 for(k=1;k<=j;k++) { 32 33 // printf("dp[%d][%d]:%d\n",i,j,dp[i][j]); 34 // cout<<"dp[i-1][k-1]+abs(a[j]-a[k])*abs(a[j]-a[k]): "<<dp[i-1][k-1]+abs(a[j]-a[k])*abs(a[j]-a[k])<<endl; 35 dp[i][j] = min(dp[i][j],dp[i-1][k-1]+abs(a[j]-a[k])*abs(a[j]-a[k])); 36 // printf("前%d天作%d道題的最小難度是%d\n",i,j,dp[i][j]); 37  } 38  } 39 printf("%lld\n",dp[m][n]); 40  } 41 return 0; 42 }

 

 

又到了一年一度的北京師範大學程序設計競賽!本次比賽的負責人萌萌噠whalyzh同窗要給你們發比賽帳號。因爲參賽隊伍衆多,面對長長的參賽名單,whalyzh同窗表示壓力山大。如今whalyzh同窗實在忙不過來,就扔了一份參賽隊伍的帳號列表給你。爲了肯定給校內隊伍頒發的各種獎項的名額,他須要知道一共有多少支校內隊伍參加了比賽。

 

Input

第一行是一個正整數T(\leq1000),表示測試數據的組數,

對於每組測試數據,

第一行是一個整數n(0 \leq n \leq100),表示隊伍數量,

接下來n行,每行是一個格式爲"學校英文名縮寫16-隊伍編號"的字符串,表示隊伍帳號,保證學校英文名縮寫只包含小寫字母,編號是正整數且不含前導零,同一學校不一樣隊伍的編號必定不一樣,來自不一樣學校的隊伍的編號可能相同。

更多信息請參考樣例。

 

Output

對於每組測試數據,輸出一行,包含一個整數,表示參賽列表中本校(即學校英文名縮寫是"bnu"的隊伍)隊伍的數量。

 

Sample Input

2
10
bac16-1
bit16-1
bitss16-1
bjfu16-1
bjtu16-1
bnu16-1
buaa16-1
cuc16-1
cugb16-1
google16-1
5
bnu16-1
bnu16-3
bnu16-5
bnu16-2
bnu16-4

Sample Output

1
5

Hint

對於第一組樣例,只有"bnu16-1"是校內隊伍。

對於第二組樣例,全部隊伍都是校內隊伍。

 

直接找到bnu的隊伍set去重便可,map標記也能夠,q神說有小坑,可是不知道在哪裏=-=

#include <iostream>
#include <set>
#include <cstdio>
#include <cstring>

using namespace std;
set<string> co;
int main()
{
//    freopen("in.txt","r",stdin);
    int T;
    cin>>T;
    while(T--) {
        co.clear();
        int n;
        cin>>n;
        for(int i = 0; i < n; i++) {
        string s;
        cin>>s;
        if(s.substr(0,6)=="bnu16-") {
            co.insert(s);
            }
        }
        cout<<co.size()<<endl;
    }
    return 0;
}
相關文章
相關標籤/搜索