题目链接:Regionals 2013 Asia - Daejeon
6500 Boxes
题意:将箱子(矩阵的1)全移动到矩阵的底部需要几步
思路:按列从下到上统计。(n,m)的矩阵,移动一个箱子(x,y),如果有c个箱子在底部,那么移动该箱子的步数是(n-x-c-1)。
AC代码:
#include
#include
int mp[110][110];
int main()
{
int t;
int i,j,n,m;
scanf("%d",&t);
while(t--){
scanf("%d %d",&n,&m);
for(i=0;i=0;i--){
if(mp[i][j]){
ans+=(n-i-c-1);
c++;
}
}
}
printf("%d\n",ans);
}
return 0;
}
/*
3
5 4
1 0 0 0
0 0 1 0
1 0 0 1
0 1 0 0
1 0 1 0
3 3
1 1 1
0 0 0
0 0 0
*/
6506 Padovan Sequence
题意:用等边三角组成多边形,每次所增加的正三角形的边长都是该多边形最长的边。(表述的不好,看题中的图会明白很多)思路:找规律,发现f[i]=f[i-2]+f[i-3]。注意long long
#include
#define LL long long
LL ans[110];
void init(){
ans[1]=1,ans[2]=1,ans[3]=1,ans[4]=2,ans[5]=2;
LL i;
for(i=6;i<=100;i++){
ans[i]=ans[i-2]+ans[i-3];
}
}
int main()
{
LL t;
LL n;
init();
scanf("%lld",&t);
while(t--){
scanf("%lld",&n);
printf("%lld\n",ans[n]);
}
return 0;
}
6508 Permutation Graphs
题意:给出两个序列把他们数字相同连线,求交点的个数
思路:将第一串数字编号,第二串按照编号译码,答案就是第二串译码后的逆序数
1 5 3 4 2 7 6
7 1 5 3 4 2 6
编号:
(1 5 3 4 2 7 6)一一对应(1 2 3 4 5 6 7)
(7 1 5 3 4 2 6)得到(6 1 2 3 4 5 7)
(6 1 2 3 4 5 7) 的逆序数为5
画个图看下比较清晰些。
AC代码:
#include
#include
#include
#include
using namespace std;
int a[100010];
int n,c[100003];
int x[100010];
vector s;
vector::iterator it;
int lowbit(int x) {
return x&(-x);
}
int sum(int x)
{
int sum=0;
while(x<=n) {
sum+=c[x];
x+=lowbit(x);
}
return sum;
}
void inster(int x,int i) {
while(x>0) {
c[x]+=i;
x-=lowbit(x);
}
}
int main()
{
int t;
int i;
scanf("%d",&t);
while(t--){
s.clear();
memset(c,0,sizeof c);
scanf("%d",&n);
for(i=0;i
题意:给出一个2*n的矩阵,取数使得到的结果最大,要求取的数不能有公共边。
思路:dp[i][j]表示前i列,状态j所取数的最大值,j==0 表示不取,j==1表示去第1行的数,j==2表示取第2行的数。状态转移见代码
AC代码:
#include
#include
#include
using namespace std;
int dp[100010][5];//0 都不选 1选上面一张(0)。2选下面一张(1)
int mp[5][100010];
int main()
{
int t;
int i,j,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(i=1;i<=2;i++){
for(j=0;j
6511 Term Project
题意: 给出n对关系,问这个n对关系中不在 成环(自环也算)中的个数。
思路:有向图的强连通,先处理自环,在计算如果强连通分量中点的个数大于1,说明成环,答案就是(n-环中的点数)
AC代码:
#include
#include
#include
using namespace std;
const int MAXN = 100010;//点数
const int MAXM = 100010;//边数
struct Edge
{
int to,next;
}edge[MAXM];
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~scc
int Index,top;
int scc;//强连通分量的个数
bool Instack[MAXN];
int num[MAXN];//各个强连通分量包含点的个数,数组编号1~scc
//num数组不一定需要,结合实际情况
void addedge(int u,int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void Tarjan(int u)
{
int v;
Low[u] = DFN[u] = ++Index;
Stack[top++] = u;
Instack[u] = true;
for(int i = head[u];i != -1;i = edge[i].next)
{
v = edge[i].to;
if( !DFN[v] )
{
Tarjan(v);
if( Low[u] > Low[v] )Low[u] = Low[v];
}
else if(Instack[v] && Low[u] > DFN[v])
Low[u] = DFN[v];
}
if(Low[u] == DFN[u])
{
scc++;
do
{
v = Stack[--top];
Instack[v] = false;
Belong[v] = scc;
num[scc]++;
}
while( v != u);
}
}
void solve(int N)
{
memset(DFN,0,sizeof(DFN));
memset(Instack,false,sizeof(Instack));
memset(num,0,sizeof(num));
Index = scc = top = 0;
for(int i = 1;i <= N;i++)
if(!DFN[i])
Tarjan(i);
}
void init()
{
tot = 0;
memset(head,-1,sizeof(head));
}
int main()
{
int t;
int i,n,a;
scanf("%d",&t);
while(t--){
init();
int ans=0;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&a);
addedge(i,a);
if(i==a) ans++;
}
solve(n);
//printf("%d\n",scc);
for(i=1;i<=scc;i++){
if(num[i]>1) ans+=num[i];
}
printf("%d\n",n-ans);
}
return 0;
}
/*
2
7
3 1 3 7 3 4 6
8
1 2 3 4 5 6 7 8
3
3
2 3 1
3
1 2 3
6
2 3 1 5 4 6
*/